Query to flatten Employee Hierarchy - hierarchy

I am just 2yrs experienced in SQL, and trying to flatten hierarchy from below table, not getting through. Appreciate your valuable suggestions.
Requirement is to show something like 'bala>>ben>>mari>>dir>>cto>>ceo>>null'
I tried this, but no luck.
declare #cn varchar(25), #mn varchar(25), #vr varchar(25), #tm varchar(25), #msg varchar(max);
declare crsr cursor for
select * from dbo.ctable ct order by ename
open crsr
fetch next from crsr into #cn, #mn
set #msg = #cn
while ##FETCH_STATUS = 0
begin
if #mn is not null set #msg = #msg + ' - '+#mn
print #msg
fetch next from crsr into #cn, #mn
end
close crsr
deallocate crsr

I got to frame this simple query, sufficing my requirement. Hope this can be fine tuned further, will be a great help. Thnx
select c.ename Emp, c.mname Lvl1, isnull(c1.mname,'') Lvl2,
isnull(c2.mname,'') Lvl3,isnull(c3.mname,'') Lvl4,isnull(c4.mname,'')
Lvl5,isnull(c5.mname,'') Lvl6
,c.ename+' >> '+c.mname+' >> '+isnull(c1.mname,'')+' >>
'+isnull(c2.mname,'')+' >> '+isnull(c3.mname,'')+' >>
'+isnull(c4.mname,'')+' >> '+isnull(c5.mname,'')
from ctable c
left join ctable c1 on c.mname=c1.ename
left join ctable c2 on c1.mname=c2.ename
left join ctable c3 on c2.mname=c3.ename
left join ctable c4 on c3.mname=c4.ename
left join ctable c5 on c4.mname=c5.ename
left join ctable c6 on c5.mname=c6.ename

Related

SQL Developer - Bind Variable "prmMediaDate" is Not Declared

I am running the below PL/SQL block in SQL Developer. I am getting the error Bind Variable "prmMediaDate" is Not Declared. Someone please tell what is missing here:
set serveroutput on;
/* RUN the following as a SCRIPT (F5) */
DECLARE
VARIABLE prmMediaDate varchar2(10);
VARIABLE prmSchdDiv varchar2(2);
VARIABLE prmSchdStore varchar2(4);
VARIABLE prmSchdAssoc varchar2(8);
BEGIN
select '07/17/2017' into :prmMediaDate FROM DUAL;
select '91' into :prmSchdDiv FROM DUAL;
select '91916559' into :prmSchdAssoc FROM DUAL;
SELECT
NVL(ODIV,LA.LABORLEV1NM) AS "schd_division"
,NVL(OLOC,LA.LABORLEV4NM) AS "schd_location"
,NVL(OZONE,LA.LABORLEV5NM) AS "schd_dept"
,NVL(O.ORGPATHTXT,LA.LABORLEV1NM||'-'||LA.LABORLEV4NM||'-'||LA.LABORLEV5NM) AS "orgpath_of_shift"
,SA.SHIFTASSIGNID AS "shiftassignid"
,SA.SHIFTCODEID AS "shiftcodeid"
,SA.ENTEREDONDTM AS "assignmnt_add_dtm"
,ST.ENTEREDONDTM AS "assignmnt_edit_dtm"
,CASE WHEN ST.ACTIONTYPEID IS NULL THEN SA.ENTEREDONDTM ELSE ST.ENTEREDONDTM END as "last_action_dt"
,ST.ACTIONTYPEID AS "last_action_cd"
,AT.SHORTNM AS "last_action_descr"
,SA.DELETEDSW AS "deletedsw"
,TRUNC(SA.SHIFTSTARTDATE) AS "shift_start_date"
,TRUNC(SA.SHIFTENDDATE) AS "shift_end_date"
,TO_CHAR(SA.SHIFTSTARTDATE, 'HH24:MI:SS') AS "shift_start_time"
,TO_CHAR(SA.SHIFTENDDATE, 'HH24:MI:SS') AS "shift_end_time"
,CASE SA.SHIFTTYPEID WHEN 1 THEN 'WORK SHIFT' WHEN 2 THEN 'UNAVAIL' WHEN 3 THEN 'HIDE SHFT' WHEN 4 THEN 'SCHD PAYCD EDIT' WHEN 5 THEN 'HIDE WRK SHFT' WHEN 6 THEN 'HIDE UNAVAIL DAY' ELSE 'UNDEFINED' END as "segment"
,NVL(LA.LABORLEV2DSC,'9999') AS "sell_nonsell"
,P.PERSONNUM AS "assoc_nbr"
,SA.ENTEREDONDTM AS "entered_on_dtm"
from PERSON P
JOIN SHIFTASSIGNMNT SA on SA.EMPLOYEEID = P.PERSONID
JOIN COMBHOMEACCT HA on (P.PERSONID = HA.EMPLOYEEID)
LEFT JOIN SHFTSEGORGTRAN SSOT on SSOT.SHIFTASSIGNID = SA.SHIFTASSIGNID
LEFT JOIN ORGX O on O.ORGIDSID = SSOT.ORGIDSID
LEFT JOIN SHFTASGNMNTTRC ST on ST.SHIFTASSIGNID = SA.SHIFTASSIGNID
LEFT JOIN ACTIONTYPE AT on AT.ACTIONTYPEID = ST.ACTIONTYPEID
LEFT JOIN LABORACCT LA on (LA.LABORACCTID = HA.LABORACCTID)
WHERE
TRUNC(SA.SHIFTSTARTDATE) = :prmMediaDate
AND :prmMediaDate BETWEEN HA.EFFECTIVEDTM AND (HA.EXPIRATIONDTM - 1)
AND ((:prmMediaDate BETWEEN O.EFFECTIVEDTM AND (O.EXPIRATIONDTM - 1)) OR (O.EFFECTIVEDTM IS NULL))
AND (SSOT.SEGMENTNUM = 1 OR SSOT.SEGMENTNUM IS NULL)
AND (TRUNC(SSOT.SHIFTSTARTDATE) = :prmMediaDate OR SSOT.SHIFTSTARTDATE IS NULL)
AND SA.DELETEDSW = 0
AND (O.ODIV = :prmSchdDiv OR LA.LABORLEV1NM = :prmSchdDiv)
AND P.PERSONNUM = :prmSchdAssoc;
end;
/
I have tried multiple options like declaring VARIABLE as var, set Scan ON etc.. But it didnt help.
You need to understand that declare is pl/sql and variable is part of sql*plus program commands.
So to successfully execute that code you need to remove DECLARE command.
Set Serveroutput On;
/* RUN the following as a SCRIPT (F5) */
--DECLARE
Variable Prmmediadate Varchar2(10);
Begin
Select '07/17/2017' Into :Prmmediadate From Dual;
End;
/
print :Prmmediadate
PL/SQL procedure successfully completed.
PRMMEDIADATE
--------------------------------------------------------------------------------
07/17/2017

How to implement CASE SELECT in WHERE clause

I have two tables T1 and T2
Senario 1:
Table T1 has a Column C1 with values terminal1, terminal2, terminal3
Select C1 from T1
Terminal1
Terminal2
Terminal3
Table T2 has a Column C2 with values terminal1, terminal2
Select C2 from T2
Terminal1
Terminal2
Senario 2
Table T2 can sometimes be null
Select C2 from T2
(null)
(null)
My Output has to be
When Senario 1 Then
Terminal1
Terminal2
When Senario 2 Then
Terminal1
Terminal2
Terminal3
i.e when table T1 and T2 have common values I want only the matching values
and
when Table T2 has null values then I want all the values
from table T1
It seems that what you need is a left outer join. Outer joins allow us to conditionally join tables.
This version of your query will return STORE_TERMINAL_LOCATION for all the rows in SP_RETAIL_TRANSACTION and matching values only of SP_TEMP_LOOKUP.AIRPORT_TERMINAL.
SELECT DISTINCT A.STORE_TERMINAL_LOCATION, B.AIRPORT_TERMINAL
FROM SP_RETAIL_TRANSACTION A,
left outer join SP_TEMP_LOOKUP B
on A.STORE_TERMINAL_LOCATION = B.AIRPORT_TERMINAL
Your question needs some proper formatting and elaborate more on the problem you are facing. I assume, you need a statement, which shows what values intersect, and if they do not - show only tables A. For that clause, you need to use inner joins and case structure. For example:
select
ter."HEATHROW_TERMINAL",
case
when lok."HEATHROW_TERMINAL" is not null then
'Terminal is in both tables'
else
'Terminalis only in main table'
end terminal_state
from
test_terminal_v ter,
test_lookup_v lok
where
ter."HEATHROW_TERMINAL" = lok."HEATHROW_TERMINAL"(+)
wheres, test_terminal_v (A) has values "5","4","2","3" and test_lookup_v (B) has "4","2","3".
Hope it helps.
After comments: there are several approaches. 1) You can use temporary tables. Create one and the code is:
begin
insert into test_term_tmp
select
ter.terminal
from
test_terminal_v ter,
test_lookup_v lok
where
ter.terminal = lok.terminal;
if sql%rowcount = 0 then
insert into TEST_TERM_TMP
select
ter.terminal
from
test_terminal_v ter;
end if;
end;
or 2) use types, for example:
declare
type t_term_tab is table of number index by binary_integer;
l_term t_term_tab;
l_i number := 1;
begin
for l_rec1 in (
select
ter.terminal
from
test_terminal_v ter,
test_lookup_v lok
where
ter.terminal = lok.terminal)
loop
l_term(l_i) := l_rec1.terminal;
l_i := l_i + 1;
end loop;
if l_term.first is null then
l_i := 1;
for l_rec2 in (
select
ter.terminal
from
test_terminal_v ter)
loop
l_term(l_i) := l_rec2.terminal;
l_i := l_i + 1;
end loop;
end if;
end;
Test the performance, based on your data. Hope it helps.
Thank you Guys, I think I found the answer
select distinct T1.C1, T2.C2
from T1 ,T2
where T2.C2=T1.C1 or T2.C2 is null;
Where in my code it was
select distinct A.STORE_TERMINAL_LOCATION,B.AIRPORT_TERMINAL
from SP_RETAIL_TRANSACTION A,SP_TEMP_LOOKUP B
where B.AIRPORT_TERMINAL=A.STORE_TERMINAL_LOCATION or B.AIRPORT_TERMINAL is null;

Proc sql to Pull data from different tables recursively

I need to perform a recursive count operation on tables but here are the challenges that I am facing with.
Lets say I have tables A, B, C, D, E, F, .... Z
Here is the code snippet of what I have,
Proc sql;
create table temp as(
select count(*)
from a
inner join b on a.id = b.id
inner join c on a.id = c.id
inner join d on a.id = d.id
where <condition>
);
Once this code is complete I need to run the same query with B, C, D and E and update the result in same temp table that I am trying to create. This way I have to do for the entire table list that I have.
Is there a recursive sql to do this. I don't require a separate macro to call the query each time with different tables.
I would not do it quite this way.
proc sql;
create table temp as (
select count(case when n(a.id,b.id,c.id,d.id)=4 then 1 else 0 end) as abcd_count,
count(case when n(b.id,c.id,d.id,e.id)=4 then 1 else 0 end) as bcde_count
from a outer join b on a.id=b.id
outer join c ... etc.
;
quit;
IE, just do one join and use case when... to determine what has the counts you need. Here I use n() to identify records with all 4 ids on them.

Decode with alias name in cursor

I want to use decode function in cursor with alias names to avoid column ambiguity so i used below approach.
I have code such as:
declare
cl number;
cursor c is
select c1.rowid,c1.col1,
DECODE(c1.col2, 'XYZ', c1.col3, 10) cl
from table1 d,table2 c1 where c1.process_id=13525 and d.col3(+)=cl;
begin
for rec in c
loop
dbms_output.put_line(NVL(rec.cl,'-1'));
end loop;
end;
In this, when i will fire query by removing condition 'and d.col3(+)=cl' it will retrieve me data with the value of 'cl' . But when i assign this condtion it will not retrive data and not go in for loop of cursor.I have a matching data in d.col3.
Suppose if i will get cl as 5 then it is also present in d.col3 then it should give me data i did this because i need to remove duplicate records.Because with that single condition i will get duplicate records.Here col3 in d table is as primary key.
So i am not getting why it will not go in for loop as it gets value from query.
You can't use alias in WHERE clause: Using an Alias in a WHERE clause
In such cases, a sub-query or a CTE might help. Something like that (untested!):
with V as (
select c1.rowid rid, ,c1.col1, c1.process_id,
DECODE(c1.col2, 'XYZ', c1.col3, 10) cl
from table2 c1)
select V.rid, V.col1, V.cl from table1 d,V
where V.process_id=13525 and d.col3(+)=V.cl;
After getting suggestion that using WITH clause, My approach to retrieve data through DECODE() using alternative table name is:
declare
cl number;
cursor c is
with V as (
select c1.process_id,
DECODE(c1.col2, 'BANDM', c1.col3, 10) cl
from table2 c1)
select c1.rowid rid,c1.col1, V.cl from table1 d,V,table2 c1
where V.process_id=1
and d.col3(+)=V.cl
and c1.col3=V.cl;
begin
for rec in c
loop
dbms_output.put_line(NVL(rec.rid,'-1'));
dbms_output.put_line(NVL(rec.cl,'-1'));
end loop;
end;
Another solution without WITH clause is :
declare
c2 number;
cursor c is
select c1.process_id
c1.rowid,
c1.col1,
DECODE(c1.col2, 'BANDM', c1.col3, 10) as c2
from table1 d,
table2 c1
where c1.process_id=1
and d.col3(+) = DECODE(c1.col2, 'BANDM', c1.col3, 10);
begin
for rec in c
loop
dbms_output.put_line(NVL(rec.rid,'-1'));
dbms_output.put_line(NVL(rec.c2,'-1'));
end loop;
end;

Limit the subquery results in DQL

I want to use LIMIT 1 clausule on the subquery in SELECT in DQL query...How can I do that?
"SELECT partial p.{productId, productName, count, price, utwTs},
(
SELECT pp.fileName
FROM AdminBundle:ProductPhoto pp
WHERE pp.productId = p.productId
// LIMIT 1 <--- here
) AS photo_name,
u.avatarName
FROM AdminBundle\Entity\Product p
LEFT JOIN AdminBundle\Entity\Users u WITH u.id = p.userId
LEFT JOIN AdminBundle\Entity\Shop sh WITH sh.userId = u.id
LEFT JOIN AdminBundle\Entity\Stand s WITH p.standId = s.standId
WHERE p.active = 1 and p.productId > 0";
How can I do this? I can't use native sql, becuase pagination (knpbundle) won't work.
That's not possible for security reasons ...
see this -> http://www.doctrine-project.org/jira/browse/DDC-885
eventually you can still make you subquery into a query and limit results with ->setMaxResults( XX ) , et use it into your main query.

Resources