retrieving rows with max date - sql

I have two tables like this:
Table1 (Number column is unique)
Number | date
1234 2008-10-06 17:11:00
5678 2005-10-19 16:20:00
9023 2005-12-09 16:20:00
4243 2009-01-06 17:11:00
5234 2009-01-14 17:11:00
Table 2
Number | code
1234 A1
1234 B1
5678 A1
9023 A1
4243 C1
5234 C1
I am trying to retrieve data from these two tables so that I get only one row for each code in Table 2 that is the most recent (from table 1).
Based on this example, my result would be:
1234 A1 (because thats the one with latest date)
1234 B1 (because thats the one with latest date)
5234 C1 (because thats the one with latest date)

Select Distinct T1.number, T2.code
From Table2 T2
Join Table1 T1
On T1.Number = T2.Number
And T1.date =
(Select Max(Date) From Table1
Where Number = T2.Number)
EDIT: to fix issue noted in comment:
Select Z.Number, Z.Code
From (Select A.number, A.code, B.date
From Table2 A Join Table1 B
On B.Number = A.Number) Z
Where Z.Date =
(Select Max(Date)
From Table2 A Join Table1 B
On B.Number = A.Number
Where code = Z.Code)

Analytic function solution. This is for Oracle; if you're using another RDBMS it may not work. If there are multiple rows with the same date for a given code, this will arbitrarily select one.
SELECT number, code FROM (
SELECT t1.number,
t1.code,
row_number() OVER ( PARTITION BY t1.code ORDER BY t2.date DESC ) date_sort_key
FROM t1, t2
WHERE t2.number = t1.number
)
WHERE date_sort_key = 1
Substituting rank() for row_number() would make it report multiple entries where there is a duplicate date.

Here is a version of Dave's answer that works on SQL Server
SELECT number, code FROM (
SELECT Table2.number,
Table2.code,
row_number() OVER ( PARTITION BY table2.code ORDER BY table1.date DESC ) date_sort_key
FROM table1, Table2
WHERE Table2.number = table1.number
) a
WHERE date_sort_key = 1

This works for SQL SERVER
CREATE table Table1 (number int, date datetime)
INSERT Table1 VALUES (1234, '2008-10-06 17:11:00')
,(5678, '2005-10-19 16:20:00')
,(9023, '2005-12-09 16:20:00')
,(4243, '2009-01-06 17:11:00')
,(5234, '2009-01-14 17:11:00')
CREATE table Table2 (number int, code varchar(2))
INSERT Table2 VALUES (1234, 'A1 ')
,(1234, 'B1')
,(5678, 'A1')
,(9023, 'A1')
,(4243, 'C1')
,(5234, 'C1')
SELECT DISTINCT
a.number
,a.code
FROM Table2 a
INNER JOIN Table1 b ON a.number = b.number
INNER JOIN (
SELECT
t2.code
,MAX(t1.date) as date
FROM Table2 t2
INNER JOIN Table1 t1
ON t1.Number = t2.Number
GROUP BY t2.code
) c ON b.date = c.date

Related

How to get data from one table based on a column from another table?

I have two tables, sample data below
tblID (ID, Quantity, Project, Region, Date)
tblAltID(ID, AltID)
tblID
ID
Quantity
Project
Region
Date
123
1
1
US
08-09-2022
tblAltID
ID
AltID
123
[456,789]
I want to be able to search for a specific 'ID' and have it bring up the data for the 'AltID', this is what I have so far (The alternate IDs in this table are formatted like "[123, 456, 789]")
Select a.ID, b.AltID, a.Quantity, a.Project, a.Region, a.Date
From tblID as a
Inner Join (Select ID, AltID From tblAltID CROSS JOIN UNNEST(AltID)) as b on a.ID
= b.ID
Where ID = '123'
and Date = (Select max(Date) from tblID
Order By Quantity Desc
For example the ID is '123', its alternates are '456' and '789', I need to obtain the quantity, project, region, and date for 123, 456, and 789. Should look something like this ->
ID
AltID
Quantity
Project
Region
Date
123
null
1
3
US
08-09-2022
123
456
1
1
US
08-09-2022
123
789
2
2
Europe
08-09-2022
For reference, all of the alternate IDs also exist in the ID table. So, I could search for ID = 456 and find the quantity, project, region, and date that way. In this example, 123, and 789 would be the alternates.
Select a.ID, b.AltID, a.Quantity, a.Project, a.Region, a.Date
From tblID as a
JOIN tblAltId as b ON b.AltId = a.ID
WHERE a.ID = '123'
AND Date = (Select max(Date) from tblID
Order By Quantity Desc
You Could use simple union code if you need only search one time in
your tblAltID. You need to show all records in the tblID where
tblID.ID=123 and also show all records related to the tblAltID where
tblAltID.ID = 123 and in this case the query should consider that the join condition between tblAltID and tblID is tblAltID.AltID = tblID.ID to show the all info related to the alt IDs as the following code sample:
Select t1.ID, t1.Quantity, t1.Project, t1.Region, t1.Date
From tblID t1
where t1.ID = 123
union
Select t1.ID, t1.Quantity, t1.Project, t1.Region, t1.Date
From tblID t1
inner join (Select ID, AltID From tblAltID CROSS JOIN UNNEST(AltID)) t2
on t1.ID = t2.AltID
where t2.ID = 123
Or you can use the following cte code too:
;with cte (ID, Quantity,Project,Region,Date, ALtID) As (
Select t1.ID, t1.Quantity, t1.Project, t1.Region, t1.Date, t2.AltID
From tblID t1
left join (Select ID, AltID From tblAltID CROSS JOIN UNNEST(AltID))
t2 on t1.ID = t2.ID
where t1.ID = 123
union All
select t1.ID, t1.Quantity, t1.Project, t1.Region, t1.Date,null as
AltID
from tblID t1
inner join cte c on t1.ID = c.AltID
)
Select *
from cte t

First date from second table where date is bigger than date in table first oracle

I want pull out the date from second table. My second table may have a over 100 dates to a unique record(A,B,C). I have I first Table :
Name Count Data1
A 1 20190201
B 3 20190201
C 6 20190201
and the second table :
Name Date
A 20190101
B 20190203
A 20190102
B 20190103
C 20190305
C 20190809
A 20190304
B 20190405
I want to first table pull out the date first date from second table when date is bigger than the date1 from first table.
The result must be :
Name Count Data1 Date2
A 1 20190201 20190304
B 3 20190201 20190203
C 6 20190201 20190305
How to extract the date. It must be a procedure or another solution.
Thanks for help :)
use join and min()
select t1.name,t1.data1,t1.count,min(t2.date) as date2
from table1 t1 join table2 t2
on t1.name=t2.name
and t1.date<t2.date
group by t1.name,t1.date,t1.count
You want the earliest date from the second table that is also greater than the date in the first table:
There are multiple solutions including a correlated sub-query:
SELECT t1.*,
( SELECT MIN( "DATE" )
FROM Table2 t2
WHERE t1.name = t2.name
AND t1.data1 < t2."DATE" ) AS data2
FROM table1 t1
or
SELECT name,
"COUNT",
data1,
data2
FROM (
SELECT t1.*,
t2."DATE" AS data2,
ROW_NUMBER() OVER ( PARTITION BY t1.name ORDER BY t2."DATE" ) AS rn
FROM table1 t1
INNER JOIN table2 t2
ON ( t1.name = t2.name AND t1.data1 < t2."DATE" )
)
WHERE rn = 1
You can simply use aggregation:
select t1.name, t1.count, t1.data1, min(t2.date) date2
from table1 t1
inner join table2 t2 on t1.name = t2.name and t2.date > t1.data1
group by t1.name, t1.count, t1.data1
You need analytical function:
SELECT NAME, COUNT_, DATA1, DATE2 FROM
(SELECT T1.NAME, T1.COUNT_, T1.DATA1,
ROW_NUMBER()
OVER (PARTITION BY T1.NAME ORDER BY T2.DATE) AS RN,
T2.DATE AS DATE2
FROM TABLE1 T1 JOIN TABLE2 T2
ON (T1.NAME = T2.NAME))
WHERE T2.DATE > T1.DATA1
WHERE RN = 1
Cheers!!

SQL Get duplicate records from one table that exist in another table

I want to get the records from Table1 where it has more than on 1 record for same Access Number, but at the same time this Access Number should also be present in Table2.
Example :
Table1
Access Number
- 1000
- 1000
- 1000
- 2000
- 3000
- 4000
- 5000
- 5000
Table2
Access Number Value
- 1000 - Test1
- 2000 - Test2
- 3000 - Test3
The result of the query should be 1000.
This is what i've got to so far, please suggest.
SELECT a.AccessNumber from Table1 a
JOIN Table2 b on b.AccessNumber = a.AccessNumber
Group by a.AccessNumber
HAVING COUNT(1) > 1;
EDIT :
I would also need a column value from Table2 along
SELECT a.AccessNumber, b.Value from Table1 a
JOIN Table2 b on b.AccessNumber = a.AccessNumber
Group by a.AccessNumber
HAVING COUNT(1) > 1;
THIS ANSWERS THE ORIGINAL VERSION OF THE QUESTION.
I would use exists:
select t1.AccessNumber
from Table1 t1
where exists (select 1 from table2 t2 where t2.AccessNumber = t1.AccessNumber)
group by t1.AccessNumber
having count(*) > 1;
This works even if you have duplicates in table2.
-- Please try this code
Create table #table1 (Accessnumber int)
Create table #table2 (Accessnumber int)
go
truncate table #table1
insert into #table1 values
(1000)
,(1000)
,(1000)
,(2000)
,(3000)
,(4000)
,(5000)
,(5000)
insert into #table2 values
(1000)
,(2000)
,(3000)
select t1.Accessnumber, count(*)NoOfRecords
from #table1 t1
inner join #table2 t2 on t2.Accessnumber = t1.Accessnumber
group by t1.Accessnumber
having count(*)>1
You can use ROW_NUMBER() to rank the Table1 query and join Table2 with result. Here is the sample query.
SELECT AccessNumber,RN
FROM
( SELECT a.AccessNumber
, ROW_NUMBER() OVER(PARTITION BY a.accessNumber, ORDER BY A.accessNumber) AS RN
FROM Table1 a
) O
JOIN Table2 b on b.AccessNumber = o.AccessNumber
WHERE RN > 1

Merge two sql queries select and count

Hello I have two sql queries and i would like to merge or combine them
Query1:
Select TableA.Name, TableB.Date
from TableA, TableB
where ID = ID_used;
Query2:
SELECT count(Date)
FROM (SELECT DISTINCT Date
FROM TableA, TableB
group by Date;
I tried:
Select TableA.Name, TableB.Date
from TableA, TableB
where ID=ID_used inner join (SELECT count(Date)
FROM (SELECT DISTINCT Date
FROM TableA, TableB
group by Date)
But it gives syntax error in union query.
The result what I need: Name, count result.
Any Idea?
Test datas:
TableA
---------------------
Name ID
---------------------
John 1001
Peter 1002
TableB
-----------------------
Date ID_used
-----------------------
2015.05.01.AM 1001
2015.05.01.AM 1001
2015.05.01.AM 1002
2015.05.01.PM 1001
2015.05.01.PM 1001
2015.05.01.PM 1002
2015.05.01.PM 1002
2015.05.02.PM 1002
Results have to be:
John 2
Peter 3
As I understand it what you need is something like this:
(Although I am not sure because you didn't add test data and expected results)
Select t1.Name,t2.Date,
(select count(date)
from (select distinct date
FROM TableA,TableB
GROUP BY Date)) as datecount
from TableA t1
join TableB t2
on t1.ID = t2.ID_used
UPDATE: I think this is what you are looking for: SQLFIDDLE
select t1.id, t1.name, count(t2.Date)
FROM TableA t1
JOIN (
SELECT Distinct id_used,Date
FROM TableB) t2
ON t1.id = t2.id_used
GROUP by t1.id
EDIT: I tried this in ms access 2010:
NOTE: I couldn't use the keyword Date as a column name so changed to mydate
select t1.id, t1.name, count(t2.mydate) as datecount
FROM TableA t1,
(SELECT Distinct id_used,mydate
FROM TableB) t2
WHERE t1.id = t2.id_used
GROUP by t1.id,t1.name
That worked but I don't recommend using joins without the join or on keywords so here is one that is better readable and also works:
select t1.id, t1.name, count(t2.mydate) as datecount
FROM TableA t1
INNER JOIN (
SELECT Distinct id_used,mydate
FROM TableB) t2
ON t1.id = t2.id_used
GROUP by t1.id,t1.name
This returns the count of distinct dates from tableB for each Name in tableA:
Select a.Name, COUNT(DISTINCT b.Date)
from TableA AS a JOIN TableB AS b
ON ID=ID_used
group by a.Name
Use tablename before the column name
Select TableA.Name,TableB.Date from TableA, TableB where ID=ID_used;

SQL Select row from table with some minimum value from another table

I suppose this is not so hard but I can not get it.
For example I have table T1:
ID
-----
1000
1001
And I have table T2:
ID GROUP DATE
--------------------------
1000 ADSL 2.2.2012
1000 null 3.2.2012
1000 NOC 4.2.2012
1001 NOC 5.2.2012
1001 null 6.2.2012
1001 TV 7.2.2012
I want to select from T1 only the row that has as GROUP value NOC from T2 but only if NOC group is for the minimum DATE value in T2.
So my result in this case would be only 1001 because for its minimum DATE 5.2.2012 Group is NOC!
I do not want any joins and I can not use default values for IDs (where id=1000 or id=1001) because this is just example of some big table.
Important also is that I can not use t1.id = t2.id because in some application where I am using this I can not write the whole SQL expression but only partial. I can only use id.
I tried something like:
select id
from t1
where
id in (select id from t2
where group = 'NOC'
and date in (select min(date) from t2
where id in (select id from t1)
)
)
But this does not work.
I know it seems little confusing but I really can't use where t1.id = t2.id
Thanks
If T2.ID is a foreign key referencing T1.ID, you don't really need the T1 table, because all the IDs could be obtained from T2 only:
SELECT o.ID
FROM T2 AS o
WHERE EXISTS (
SELECT MIN(i.DATE)
FROM T2 AS i
WHERE i.ID = o.ID
HAVING MIN(i.DATE) = o.DATE
)
WHERE o."GROUP" = 'NOC'
But if you insist on involving T1, you just need to modify the above like this:
SELECT *
FROM T1
WHERE ID IN (
SELECT o.ID
FROM T2 AS o
WHERE o."GROUP" = 'NOC'
AND EXISTS (
SELECT MIN(i.DATE)
FROM T2 AS i
WHERE i.ID = o.ID
HAVING MIN(i.DATE) = o.DATE
)
)
Can you do this in multiple steps?
First of all, to get the minimum date per id, you would need:
select id, peoplegroup, min(date)
from t2
group by id
That will give you
1000 ADSL 2.2.2012
1001 NOC 5.2.2012
Call this table t3.
Then do
select id
from t3
where id in (
select id from t1
)
Try this:
select id from t1 where id in
(select id from t2 where group = 'NOC' and date =
(select min(date) from t2 where id = t1.id))