Pick the missing records with latest dates in Oracle - sql

I have 2 tables with only 3 common fields.
I wrote the below query to pick up the missing data with Latest date in table 1.
Employee Category Date_Field First_Name Last_Name Status Result
100 Type1 30/08/2010 A B Present Good
200 Type1 1/09/2010 C D Hello Alt
100 Type3 30/09/2010 A B
100 Type1 30/09/2012 A B
Employee Category Date_Field
100 Type1 03/11/2016
100 Type3 30/09/2010
100 Type4 11/10/2010
200 Type3 12/12/1989
My Query is
with x1 as (SELECT Employee,Category,Date_Field,First_Name,Last_Name,Status,Result,' ' as Somefield from table 1
where not exists
(select 1 from table2
where table1.employee=table2.employee and table1.category = table2.Category
and table1.Date_Field = table2.Date_Field)),
x2 as (select Employee,Category,Max(Date_Field) as DateField from x1 group by Employee)
select x1.Employee,x1.Category,x1.Date_Field,x1.First_Name,x1.Last_Name,x1.Status,x1.Result,x1.Somefield from x1,x2
where x1.Employee = x2.Employee and x1.Date_Field=x2.DateField and x1.Category=x2.Category
order by x1.Employee;
The Current Ouptput i get is
Employee Category Date_Field First_Name Last_Name Status Result
100 Type1 30/09/2012 A B
200 Type1 1/09/2010 C D Hello Alt
Can i get this query modified so that If there ia record for the same employee with latest date and category in table 2, my output should not have that record.
So the expected Output is
Employee Category Date_Field First_Name Last_Name Status Result
200 Type1 1/09/2010 C D Hello Alt
Your help is much appreciated

Hope you can ignore the datefield for the NOT EXISTS clause.
SELECT * FROM TABLE1 T1
WHERE NOT EXISTS
(
SELECT 'x' FROM TABLE2 T2
WHERE T1.EMPLOYEE = T2.EMPLOYEE
AND T1.CATEGORY = T2.CATEGORY
AND T2.DATEFIELD >= T1.DATEFIELD
)

Related

How to join only latest date values from another table and prevent duplication

I'm trying to lookup a unique value from table b and get it into table a.
Table b stores multiple values that are changing by date.
I would like to join but only getting the values with the latest date from table b.
Table a
Unique ID
1
2
Table b
Date Unique ID Price
01/01/2019 1 100
01/02/2019 1 101
01/03/2019 1 102
01/01/2019 2 90
01/02/2019 2 91
01/03/2019 2 92
Expected result
Unique ID Price Date
1 102 01/03/2019
2 92 01/03/2019
Appreciate your help!
Have a sub-query that returns each UniqueID together with its max date. IN that result.
select * from tablename
where (UniqueID, date) in (select UniqueID, max(date)
from tablename
group by UniqueID)
You want correlated subquery :
select b.*
from tableb b
where b.date = (select max(b1.date) from tableb b1 where b1.UniqueID = b.UniqueID);
If you want to go with JOIN then you can do JOIN with subquery :
select a.UniqueID , b.Price, b.Date
from tablea a inner join
tableb b
on b.UniqueID = a.UniqueID
where b.date = (select max(b1.date) from tableb b1 where b1.UniqueID = a.UniqueID);
A correlated subquery?
select b.*
from b
where b.date = (select max(b2.date) from b b2 where b2.unique_id = b.unique_id);

Get most recent records where one field is not null

I'm looking to narrow down my database to have only the most records. The most recent records need to have a value in a specific field.
ID Account_nbr Date Name
1 622 7/10/2018 Stu
2 622 7/24/2018
3 151 7/18/2018 Taylor
4 151 7/24/2018 Taylor
This is an example of the database.
I want the code to do this:
ID Account_nbr Date Name
1 622 7/10/2018 Stu
4 151 7/24/2018 Taylor
I have tried the following code:
Select m.*
FROM [table] m
INNER JOIN
(
SELECT last(Date) as LatestDate
,account_nbr
FROM [table]
WHERE Name IS NOT NULL
GROUP BY account_nbr
) b
ON m.Date = b.LatestDate
AND m.account_nbr = b.account_nbr
The output only included the most recent date and did not take into account records that were null in the name field.
I would do :
select t.*
from table as t
where t.name is not null and
t.date = (select max(t1.date)
from table as t1
where t1.account_nbr = t.account_nbr
);
Try this:
Select
m.*
From
[table] As m
Where
m.[Date] In
(Select Max([Date])
From [table] As T
Where T.[Name] Is Not Null
And T.account_nbr = m.account_nbr)

Join with table

Say I have two tables as below where Table A has columns name and type where each name may appear many times and with different type and Table B has unique code, name and sum.
Table A
John Type1
Mark Type2
John Type1
Mark Type3
John Type4
Paul Type5
Table B
1 John 20
2 Mark 33
3 Paul 22
4 Mark 55
5 John 46
Now what I want is something like this:
Table C
1 John 20 Type1
2 Mark 33 Type2
3 Paul 22 Type5
4 Mark 55 Type2
5 John 46 Type1
Normally Table A should contain unique entries with one type for each name and I could do a right join Table B on name to get what I want. But now if I do right join I get duplicate entries on Table C because name has duplicates types in Table A. How do I solve this?
Try this
WITH TableAA
AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY NAME ORDER BY NAME,TYPE) RN
,name
,type
FROM TableA
)
SELECT
B.*
,(
SELECT type from TableAA A WHERE A.name= B.name AND A.RN=
ISNULL(NULLIF((SELECT COUNT(1) FROM TableB C WHERE C.NAME=B.name
and C.no < B.no),0),1)
) AS Type
FROM
TableB B
SQLFiddle Demo
You can try this :
SELECT A.*,B.TYPE
FROM dbo.TABLE_2 A RIGHT JOIN
(
SELECT DISTINCT(NAME),MIN(TYPE)TYPE
FROM TABLE_1
GROUP BY NAME
) B ON A.NAME=B.NAME
ORDER BY CODE ASC
TABLE_1= TABLE A
TABLE_2= TABLE B

Get the max value of a column from set of rows

I have a table like this
Table A:
Id Count
1 4
1 16
1 8
2 10
2 15
3 18
etc
Table B:
1 sample1.file
2 sample2.file
3 sample3.file
TABLE C:
Count fileNumber
16 1234
4 2345
15 3456
18 4567
and so on...
What I want is this
1 sample1.file 1234
2 sample2.file 3456
3 sample3.file 4567
To get the max value from table A I used
Select MAX (Count) from A where Id='1'
This works well but my problem is when combining data with another table.
When I join Table B and Table A, I need to get the MAX for all Ids and in my query I dont know what Id is.
This is my query
SELECT B.*,C.*
JOIN A on A.Id = B.ID
JOIN C on A.id = B.ID
WHERE (SELECT MAX(COUNT)
FROM A
WHERE Id = <what goes here????>)
To summarise, what I want is Values from Table B, FileNumber from Table c (where the count is Max for ID from table A).
UPDATE: COrrecting table C above. Looks like I need Table A.
I think this is the query you're looking for:
select b.*, c.filenumber from b
join (
select id, max(count) as count from a
group by id
) as NewA on b.id = NewA.id
join c on NewA.count = c.count
However, you should take into account that I don't get why for id=1 in tableA you choose the 16 to match against table C (which is the max) and for id=2 in tableA you choose the 10 to match against table C (which is the min). I assumed you meant the max in both cases.
Edit:
I see you've updated tableA data. The query results in this, given the previous data:
+----+---------------+------------+
| ID | FILENAME | FILENUMBER |
+----+---------------+------------+
| 1 | sample1.file | 1234 |
| 2 | sample2.file | 3456 |
| 3 | sample3.file | 4567 |
+----+---------------+------------+
Here is a working example
Using Mosty’s working example (renaming the keyword count to cnt for a column name), this is another approach:
with abc as (
select
a.id,
a.cnt,
rank() over (
partition by a.id
order by cnt desc
) as rk,
b.filename
from a join b on a.id = b.id
)
select
abc.id, abc.filename, c.filenumber
from abc join c
on c.cnt = abc.cnt
where rk = 1;
select
PreMax.ID,
B.FileName,
C2.FileNumber
from
( select C.id, max( C.count ) maxPerID
from TableC C
group by C.ID
order by C.ID ) PreMax
JOIN TableC C2
on PreMax.ID = C2.ID
AND PreMax.maxPerID = C2.Count
JOIN TableB B
on PreMax.ID = B.ID

SQL query help

Sorry for posting this question again. I rephrased my question a little bit.
I am trying to write a query to return rows from Table-A where multiple rows found in Table-B with STATUS = 1 for each CID column from Table-A.
So in this example CID 100 has two records found in Table-B and STATUS = 1. So I want to write a query to return this row from Table-A. I know this is a weird table design. Please help.
Here are the tables with sample data.
Table-A
-----------------------------------------
AID Name CID
---------------------------------------
10 test1 100
12 test1 100
13 test2 101
14 test2 101
15 test3 102
Table-B
------------------------------------
bID AID status
-----------------------------------
1 10 1
2 12 1
3 14 1
4 15 1
Try this query:
SELECT TableA.CID
FROM TableA
JOIN TableB ON TableA.AID = TableB.AID
WHERE TableB.status = 1
GROUP BY TableA.CID
HAVING COUNT(*) > 1
It returns 100 for your example data.
Something like this?
select aid,
status
from (select aid,
count(*) as cnt
from tableA
group by aid) as aggregated
left join tableB on tableB.aid = aggregated.aid
where aggregated.cnt > 1
If your using SQL:
WITH tableBView AS
(
SELECT AID AS xxxAID
FROM [Table-B]
WHERE status = 1
GROUP BY AID
HAVING COUNT(*) > 0
)
SELECT *
FROM [Table-A]
WHERE EXISTS (SELECT * FROM tableBView WHERE xxxAID = AID)
SELECT *
FROM Table-A a
WHERE a.CID IN
(
SELECT a.CID FROM Table-A a JOIN Table-B b USING (AID)
GROUP BY a.CID
WHERE b.status = 1
HAVING count(*) > 1
)
This is a very verbose way to do it.
Selects all columns from Table-A on rows where AID match between Table-A and Table-B and more than one row with the same CID exists in Table-A:
(Btw, I wouldn't use "-" in your table/column names. Use "_" instead.)
select
derived_table.AID,
derived_table.Name,
derived_table.CID
from
(select
table_A.AID,
table_A.Name,
table_A.CID,
count(table_A.CID) c
from
Table_A
inner join Table_B on (Table_A.AID = table_B.AID)
group by table_A.CID
) derived_table
where
c > 1