i have couple of tables with some resource data
Resource
----------
rID | rname | updatedstamp
R1 Res1 01-Jul-2015
R2 Res2 01-Jul-2015
R3 Res3 01-Jul-2015
R4 Res4 01-Jul-2015
R5 Res5 01-Jul-2015
R15 Res15 01-Aug-2015
ResourceTree
----------
parID | rID | updatedStamp
---------------------------
NULL R1 01-Jul-2015
R1 R2 01-Aug-2015
R2 R3 01-Jul-2015
R3 R4 01-Jul-2015
R4 R5 01-Jul-2015
R14 R15 01-Jul-2015
I need a select query which will fetch all records updated on or after '01-Aug-2015'. Also, I need to fetch details of child resources of any parent updated on '01-Aug-2015'
so in my case, i need to fetch all records from resource table updated on 01-Aug-2015. In my case it would be only R15.
Additionally, it should also fetch details from the Resource_Tree table where any update has happened on or post 01-Aug-2015 . In my case it would be R2 R3 R4 R5.
Results
parid rid rname
R14 R15 Res15
R1 R2 Res2
R2 R3 Res3
R3 R4 Res4
R4 R5 Res5
Query tried so far
SELECT RT.ParID,R.ID,R.Rname
FROM RESOURCES R, RESOURCETREE RT
WHERE R.RID = RT.RID
And (R.UpdatedStamp >= '01-Aug-2015' or RT.UpdatedStamp >= '01-Aug-2015')
START WITH RT.ParID ='R1' AND
CONNECT BY PRIOR RT.RID=RT.ParID
This may not be an elegant solution;
with temp_tbl_1 as (
-- get all the "rid" updatedstamp >= '01-Aug-2015' from both tables
select rID
from ResourceTree
where updatedstamp >= '01-Aug-2015'
union all
select rid
from Resource
where updatedstamp >= '01-Aug-2015'
),
temp_tbl_2 as (
select parID, rID
from ResourceTree
START WITH rID in (select distinct rID from temp_tbl_1)
CONNECT BY PRIOR RID = ParID
)
select t.parID, t.rID, r.rname
from temp_tbl_2 t
join Resource r
on r.rID = t.rID
with x as (
select rid from ResourceTree
where updatedstamp >= '01-Aug-2015'
union
select rid from Resourc
where updatedstamp >= '01-Aug-2015'
)
select r.parid, r.rid, re.rname
from ResourceTree r
left join x on r.parid = x.rid
left join Resourc re on re.rid = r.rid
where r.parid is not null
You select rid after 01-Aug-15 in the cte and then left join the other tables on ResourceTree table.
Related
I have table in below format,
Table 1
Bank
Category
Month_Year
Loan_Type
Outstanding
SI
R1
JAN-21
Home
10
SI
R1
JAN-21
Land
50
SI
R2
FEB-21
Home
30
SI
R2
MAR-21
Car
40
Table 2
Bank
Loan_Type
SI
Home
SI
Land
SI
Car
SI
Jewel
SI
Education
I would like to convert the table A and B in to below format using join/query. The data(all rows) from the table-2 should get added based of the Category and Month_Year.
BANK
Category
Month_Year
Loan_Type
Outstanding
SI
R1
JAN-21
Home
10
SI
R1
JAN-21
Land
50
SI
R1
JAN-21
Car
0
SI
R1
JAN-21
Jewel
0
SI
R1
JAN-21
Education
0
SI
R2
FEB-21
Home
30
SI
R2
FEB-21
Land
0
SI
R2
FEB-21
Car
0
SI
R2
FEB-21
Jewel
0
SI
R2
FEB-21
Education
0
SI
R2
MAR-21
Home
0
SI
R2
MAR-21
Land
0
SI
R2
MAR-21
Car
40
SI
R2
MAR-21
Jewel
0
SI
R2
MAR-21
Education
0
Principally a CROSS JOIN needed among the tables after Category and Month_Year columns are distinctly selected, and Outstanding column is added in the main query as zero for non-matching values, otherwise returning values of it such as
SELECT t2.Bank, t2.Category, t2.Month_Year, t2.Loan_Type,
NVL(t1.Outstanding,0) AS Outstanding
FROM (SELECT *
FROM (SELECT DISTINCT Category, Month_Year FROM table1)
CROSS JOIN table2) t2
LEFT JOIN table1 t1
ON t2.Category = t1.Category
AND t2.Month_Year = t1.Month_Year
AND t2.Loan_Type = t1.Loan_Type
ORDER BY t2.Category, t2.Month_Year, t1.Outstanding NULLS LAST
Demo
Create a list of all items needed and left join Table1. For example
select items.Bank, items.Category, items.Month_Year, items.Loan_Type, coalesce(t1.Outstanding, 0) Outstanding
from (
select t2.Bank, t2.Loan_Type, my.Month_Year, cat.Category
from (select distinct Month_Year
from Table1) my
cross join (select distinct Category
from Table1) cat
cross join Table2 t2
) items
left join Table1 t1 on items.Bank = t1.Bank and items.Loan_Type = t1.Loan_Type and items.Month_Year = t1.Month_Year and items.Category = t1.Category;
If there exists a table Categories replace it instead of derived categories in the query. You may also wish to generate a set of Month_Year from prameters or use a calendar table.
I have table T1 as below
RL OR FVALU TVALU
R1 O1 3291
R1 O1 3002
R1 O1 3010
R2 O1 2000
and Another Table T2 as below:
RL OR FVALU TVALU
R1 O1 3291
R1 O1 3000 3005
R1 O1 5000
R2 O1 *
Expected output should be as below:
RL OR FVALU TVALU MATCHORDOESNOT
R1 O1 3291 MATCH
R1 O1 3002 MATCH
R1 O1 3010 DONOTMATCH
R2 O1 2000 MATCH
===============================================================
How do I match values in FVALU and TVALU field from T1 to T2 ?
In above case 3002 and 3291 should match between T1 and T2 tables as well * value should match with 2000. First two column can have join. Also, Notice TVALU sometimes has value and sometimes it is Null
I have tried below query and not working : SELECT T1.RL, T1.[OR], T1.FVALU, T1.TVALU, IIf(InStr(([T2]![FVALU]),"*")>0,"MATCH",IIf([T1]![FVALU] Between ([T2]![FVALU]) And (IIf([T2]![FVALU] Is Null,[T2]![FVALU],[T2]![FVALU])),"MATCH","DONOTMATCH")) AS MATCHORDOESNOT FROM T1 INNER JOIN T2 ON (T1.[OR] = T2.[OR]) AND (T1.RL = T2.RL);
With a LEFT join of the tables and all the conditions in the ON clause:
SELECT DISTINCT T1.*,
IIF(T2.RL IS NULL, 'DONOTMATCH', 'MATCH') AS MATCHORDOESNOT
FROM T1 LEFT JOIN T2
ON T2.RL = T1.RL AND T2.[OR] = T1.[OR]
AND (T2.FVALU = T1.FVALU OR (INSTR(T2.FVALU, '*') > 0) OR (T1.FVALU BETWEEN T2.FVALU AND T2.TVALU))
Results:
RL OR FVALU TVALU MATCHORDOESNOT
R1 O1 3002 MATCH
R1 O1 3010 DONOTMATCH
R1 O1 3291 MATCH
R2 O1 2000 MATCH
id dept Person Rating
-------------------------------------------
1 ece p1 R1
2 ece p2 t1
3 eee P3 R2
4 eee p4 M
5 Civil P5 R2
6 Civil P6 t2
7 Civil P7 t2
8 Mech p8 R2
9 Mech P9 NULL
10 IT P10 R2J
11 IT P11 T2
12 IT P12 T2
I would like to fetch all the rows whose department's rating has at least one value like 'P%' and one like 'T%'.
A rather direct method uses exists:
select t.*
from t
where exists (select 1 from t t2 where t2.dept = t.dept and t2.rating like 'P%') and
exists (select 1 from t t2 where t2.dept = t.dept and t2.rating like 'T%') ;
I have following two table with sample Data.
PLACED_PERSON_INFO
*PLACED_PERSON_INFO_GUID CPR*
P1 0201026157
P2 0309929493
P3 0002170000
P4 0000011037
P5 1201006694
P6 1201009887
P7 1110007144
P8 0309906353
P9 0101002420
PLACED_PERSON_PLACES
*PP_ID PLACEMENT_DATE PLACEMENT_STOP PLACED_PERSON_INFO_GUID*
1 01-01-2014 31-12-2014 P1
2 01-01-2014 31-12-2014 P1
3 01-01-2013 31-12-2013 P2
4 01-06-2014 30-10-2014 P3
5 01-02-2014 30-10-2014 P3
6 01-01-2013 01-01-2015 P4
7 01-01-2013 30-05-2013 P4
8 01-01-2012 30-03-2013 P5
I have written the following SQL Query to get the result combining these two tables.
SQL Query :
SELECT
PPI.PLACED_PERSON_INFO_GUID, PPI.CPR
FROM PLACED_PERSON_PLACES PPP, PLACED_PERSON_INFO PPI
WHERE (PPP.PLACEMENT_DATE <= SYSDATE OR PPP.PLACEMENT_DATE IS NULL)
AND (PPP.PLACEMENT_STOP >= SYSDATE OR PPP.PLACEMENT_STOP IS NULL)
AND PPP.PLACED_PERSON_INFO_GUID (+) = PPI.PLACED_PERSON_INFO_GUID
ORDER BY PPI.CPR;
Query Result:
PLACED_PERSON_INFO_GUID CPR
P1 0201026157
P1 0201026157
P3 0002170000
P3 0002170000
P4 0000011037
P6 1201009887
P7 1110007144
P8 0309906353
P9 0101002420
But I want the following result where duplicate rows will not be shown. I do not want to use DISTINCT keyword. Can anyone help me in this result? I am using Oracle 11i.
Expected Result:
PLACED_PERSON_INFO_GUID CPR
P1 0201026157
P3 0002170000
P4 0000011037
P6 1201009887
P7 1110007144
P8 0309906353
P9 0101002420
First, you should write your query using explicit join syntax:
SELECT PPI.PLACED_PERSON_INFO_GUID, PPI.CPR
FROM PLACED_PERSON_INFO PPI LEFT JOIN
PLACED_PERSON_PLACES PPP
ON PPP.PLACEMENT_DATE <= SYSDATE AND
PPP.PLACEMENT_STOP >= SYSDATE AND
PPP.PLACED_PERSON_INFO_GUID = PPI.PLACED_PERSON_INFO_GUID
ORDER BY PPI.CPR;
If you only want one row, then you can use row_number():
SELECT PLACED_PERSON_INFO_GUID, CPR
FROM (SELECT PPI.PLACED_PERSON_INFO_GUID, PPI.CPR,
ROW_NUMBER() OVER (PARTITION BY PPI.PLACED_PERSON_INFO_GUID, PPI.CPR ORDER BY PPI.CPR) as seqnum
FROM PLACED_PERSON_INFO PPI LEFT JOIN
PLACED_PERSON_PLACES PPP
ON PPP.PLACEMENT_DATE <= SYSDATE AND
PPP.PLACEMENT_STOP >= SYSDATE AND
PPP.PLACED_PERSON_INFO_GUID = PPI.PLACED_PERSON_INFO_GUID
) p
WHERE seqnum = 1;
ORDER BY CPR;
You can add additional columns and still only get one row per pair.
Solution is :
SELECT PLACED_PERSON_INFO_GUID, CPR
FROM (SELECT PPI.PLACED_PERSON_INFO_GUID, PPI.CPR,
ROW_NUMBER() OVER (PARTITION BY PPI.PLACED_PERSON_INFO_GUID, PPI.CPR ORDER BY PPI.CPR) AS SEQNUM
FROM PLACED_PERSON_INFO PPI LEFT JOIN PLACED_PERSON_PLACES PPP
ON PPP.PLACED_PERSON_INFO_GUID = PPI.PLACED_PERSON_INFO_GUID
WHERE (PPP.PLACEMENT_DATE <= SYSDATE OR PPP.PLACEMENT_DATE IS NULL)
AND (PPP.PLACEMENT_STOP >= SYSDATE OR PPP.PLACEMENT_STOP IS NULL)
) P
WHERE SEQNUM = 1
ORDER BY CPR
I have a table with the following values (Please ignore index, here column with R1..R10 being the PK of the table.
1 R1 M1 Mo1
2 R2 M2 Mo3
3 R3 M4 Mo6
4 R4 M2 Mo1
5 R5 M7 Mo1
6 R6 M5 Mo2
7 R7 M6 Mo1
8 R8 M4 Mo4
9 R9 M9 Mo3
10 R10 M3 Mo9
I want to find a value of Mo[i] for which number of R[i] are max. For example in above case Mo1 has maximum number of R[i] values so it must return Mo1.
I have been doing the stuff using count, but not succeeded yet.
Here is what i wrote
select Mo from table1 where Mo=(select max(r.Mo),max(count((r.Mo))) from table1 )r group by r.Mo
Try this:
select Mo from
(
select Mo from
(
select Mo, count(*) cnt
from table1
group by Mo
)
order by cnt desc
) where rownum = 1;
This first groups the table by the column Mo, resulting in
Mo | cnt
----+----
Mo3 | 2
Mo2 | 1
Mo4 | 1
Mo1 | 4
Mo6 | 1
Mo9 | 1
It then orders this by the count which results in this:
Mo
---
Mo1
Mo3
Mo6
Mo2
Mo4
Mo9
And then it simply returns the first row of the result which results in Mo1.