问题
I have two tables in my SQL Server db that I want to join:
Person table:
PersonId Name DeviceId
001 John 11111
002 Eric 22222
003 Steve 33333
Device Table:
DeviceId Date
11111 2013-02-01
11111 2013-02-02
11111 2013-02-03
22222 2013-02-03
22222 2013-02-01
The result I want is the following
PersonId Name DeviceId Date IsRegistered
001 John 11111 2013-02-03 1
002 Eric 22222 2013-02-03 1
003 Steve 33333 null 0
So as you see I want a join between the tables and I only want unique values.
The data field should be the last registered (newest date). If the person has a value in the date field the IsRegistered
should have value 0
If anyone know how I can fix this I would appreciate it
回答1:
- SQLFIDDLE DEMO
Query:
SELECT
p.*, d.maxdate
FROM persons p
left join
( SELECT id, MAX(date) MaxDate
FROM device
GROUP BY id
) d ON p.deviceid = d.id
ORDER BY d.maxdate DESC;
| PERSONID | NAME | DEVICEID | MAXDATE |
-----------------------------------------------------------------
| 1 | John | 11111 | February, 03 2013 02:00:00+0000 |
| 2 | Eric | 22222 | February, 03 2013 00:00:00+0000 |
| 3 | Steve | 33333 | (null) |
I see that you also need isRegistered
column, here it is:
- SQLFIDDLE WITH last column added
Query:
SELECT
p.*, d.maxdate, case when d.maxdate is null then 0 else 1 end as isRegistered
FROM persons p
left join
( SELECT id, MAX(date) MaxDate
FROM device
GROUP BY id
) d ON p.deviceid = d.id
ORDER BY d.maxdate DESC
;
Results:
| PERSONID | NAME | DEVICEID | MAXDATE | ISREGISTERED |
--------------------------------------------------------------------------------
| 1 | John | 11111 | February, 03 2013 02:00:00+0000 | 1 |
| 2 | Eric | 22222 | February, 03 2013 00:00:00+0000 | 1 |
| 3 | Steve | 33333 | (null) | 0 |
回答2:
Try this:
SELECT
p.PersonId,
p.Name,
p.DeviceId,
d.MaxDate AS "Date",
CASE
WHEN d.deviceID IS NULL THEN 0
ELSE 1
END AS IsRegistred
FROM Person p
LEFT JOIN
(
SELECT DeviceId, MAX(Date) MaxDate
FROM Device
GROUP BY DeviceId
) d ON p.DeviceId = d. DeviceId;
SQL Fiddle Demo
This will give you:
| PERSONID | NAME | DEVICEID | DATE | ISREGISTRED |
-------------------------------------------------------------------------------
| 1 | John | 11111 | February, 03 2013 02:00:00+0000 | 1 |
| 2 | Eric | 22222 | February, 03 2013 02:00:00+0000 | 1 |
| 3 | Steve | 33333 | (null) | 0 |
Or: Using the ranking function ROW_NUMBER()
you can do this:
WITH CTE
AS
(
SELECT
p.PersonId,
p.Name,
p.DeviceId,
d.deviceID AS ddeviceID,
d.Date,
ROW_NUMBER() OVER(PARTITION BY p.PersonID, p.DeviceId
ORDER BY Date DESC) rownum
FROM Person p
LEFT JOIN Device d ON p.DeviceId = d. DeviceId
)
SELECT
PersonID,
Name,
DeviceId,
Date,
CASE
WHEN ddeviceID IS NULL THEN 0
ELSE 1
END AS IsRegistred
FROM CTE
WHERE rownum = 1;
Updated SQL Fiddle Demo
This will give you the same result.
来源:https://stackoverflow.com/questions/14338332/joining-two-mssql-tables-unique-values