Question

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

Was it helpful?

Solution

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 |

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top