2009-11-23 170 views
15

我正在尝试编写一个查询,以从每个唯一设备的GPSReport表中返回最新的GPS位置。表中有50个设备,所以我只需要返回50行。对一列的SELECT DISTINCT,返回多个其他列(SQL Server)

这里是我到目前为止(不工作)

SELECT TOP(SELECT COUNT(DISTINCT device_serial) FROM GPSReport) * FROM GPSReport AS G1 
RIGHT JOIN 
(SELECT DISTINCT device_serial FROM GPSReport) AS G2 
ON G2.device_serial = G1.device_serial 
ORDER BY G2.device_serial, G1.datetime DESC 

这将返回50行,但没有返回每个device_serial唯一行。它返回第一个设备的所有报告,然后返回第二个设备的所有报告等。

是我在一个查询中想要做的可能吗?

+0

给你的数据模式的相关部分可能有助于以后这个惊人的结果。 – Jason 2009-11-23 20:17:05

+0

你在行上有任何唯一的ID吗? – artdanil 2009-11-23 20:19:18

+0

对不起,该表格包含以下列:device_serial,datetime,triggerID,纬度,经度,速度,地址。 PK由device_serial,datetime,triggerID,纬度,经度列组成。 – mwalsher 2009-11-23 20:32:20

回答

15
SELECT * FROM 
GPSReport AS G1 
JOIN (SELECT device_serial, max(datetime) as mostrecent 
     FROM GPSReport group by device_serial) AS G2 
ON G2.device_serial = G1.device_serial and g2.mostrecent = g1.datetime 
ORDER BY G1.device_serial 
+0

如果您只需要设备和时间码,则只需使用子查询。 SELECT device_serial,max(datetime)as mostrecent FROM GPSReport group by device_serial – Hogan 2009-11-23 20:24:05

+0

这不太可能,但如果存在多个具有相同datetime和service_serial的记录,这可能仍会返回重复项。尽管使用分组函数和聚合函数绝对是解决方案。 – MandoMando 2009-11-23 20:26:35

+0

嗯我不这么认为,不在sql-server 2005. max只会返回一个值,即使值相同。 (这是max()技巧用于将其他常量字段的列添加到聚合查询中的原因 – Hogan 2009-11-23 20:34:04

2

你有一个正确的加入,所以如果你有在表GPSReport设备序列号大于1分​​的记录,它会得到所有的记录,然后联合从SELECT DISTINCT device_serial FROM GPSReport收到的唯一列表。

1

尝试:

Select r.* 
    From GPSReport r 
    Where datetime = 
     (Select Max(DateTime) 
     From GPSReport 
     Where device_serial = r.device_serial) 
1

如何这样的事情 - 因为我无法运行它,我希望我的synatx是不完美的

select * 
    from (
    select device_serial, [datetime], triggerID, latitude, longitude, speed, [address], 
     ROW_NUMBER() over (partition by device_serial order by device_serial asc, [datetime] desc) as row 
     from gpsreport 
) as data 
    where row = 1 

您可能需要修改order by子句选择首选记录,如果有多个具有相同的device_serial和日期时间的倍数

1

我会用公用表表达式(CTE),像这样:

With ResultTable (RowNumber 
       ,device_serial 
       ,datetime 
       ,triggerID 
       ,latitude 
       ,longitude 
       ,speed 
       ,address) 
AS 
(
    SELECT Row_Number() OVER (PARTITION BY device_serial 
            ORDER BY datetime DESC) 
      ,device_serial 
      ,datetime 
      ,triggerID 
      ,latitude 
      ,longitude 
      ,speed 
      ,address 
     FROM GPSReport 
) 
    SELECT device_serial 
      ,datetime 
      ,triggerID 
      ,latitude 
      ,longitude 
      ,speed 
      ,address 
     FROM ResultTable 
    WHERE RowNumber = 1 
22
WITH DEDUPE AS (
    SELECT * 
      , ROW_NUMBER() OVER (PARTITION BY what_you_want_for_distinct ORDER BY what_you_want_for_distinct) AS OCCURENCE 
    FROM tablename 
    ) 
SELECT * FROM DEDUPE 
WHERE 
OCCURENCE = 1 
+2

杰出的,我喜欢它,当答案抽象出细节并展示概念时。 +1 – 2014-06-13 19:41:03

+1

你的答案绝对精彩。非常感谢发布这个。巨大的帮助。 – joelc 2015-07-27 01:07:09

+0

非常具有描述性。不过,我认为ORDER BY应该是what_you_want_to_select [DESC]而不是what_you_want_for_distinct。 – verbamour 2016-03-15 19:02:39

0

这是最后的结果不使用不同的,因为这是新的查询,其所有有益“SELECT * FROM TBL GROUP BY bandsupported“。其工作同一个鲜明提出并得到所有行

0

我发现正在尽一切的答案在计算器上

WITH cte AS /* Declaring a new table named 'cte' to be a clone of your table */ 
(SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY val1 DESC) AS rn 
    FROM MyTable /* Selecting only unique values based on the "id" field */ 
) 
SELECT * /* Here you can specify several columns to retrieve */ 
FROM cte 
WHERE rn = 1