在一列上选择 DISTINCT,返回多个其他列(SQL Server)
Posted
技术标签:
【中文标题】在一列上选择 DISTINCT,返回多个其他列(SQL Server)【英文标题】:SELECT DISTINCT on one column, return multiple other columns (SQL Server) 【发布时间】:2010-12-19 15:05:41 【问题描述】:我正在尝试编写一个查询,该查询从 GPSReport 表中返回每个唯一设备的最新 GPS 位置。表中有 50 个设备,所以我只希望返回 50 行。
这是我目前所拥有的(不工作)
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 返回唯一的行。它返回第一个设备的所有报告,然后返回第二个设备的所有报告,等等。
我试图在一个查询中做的事情可能吗?
【问题讨论】:
提供数据架构的相关部分可能会有所帮助。 行上有唯一的 id 吗? 对不起,该表有以下列:device_serial, datetime, triggerID, latitude, longitude, speed, address。 PK 由 device_serial、datetime、triggerID、latitude、longitude 列组成。 【参考方案1】: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
【讨论】:
出色,我喜欢答案抽象出细节并展示概念。 +1 您的回答绝对精彩。非常感谢您发布这个。巨大的帮助。 非常具有描述性。但是,我确实认为 ORDER BY 应该是 what_you_want_to_select [DESC] 而不是 what_you_want_for_distinct。【参考方案2】: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
【讨论】:
如果您只需要设备和时间码,您可以只使用子查询。 SELECT device_serial, max(datetime) as mostrecent FROM GPSReport group by device_serial 不太可能,但是如果有多个具有相同日期时间和 service_serial 的记录,这可能仍会返回重复项。使用 group-by 和 aggregate 函数绝对是解决方案。 hmmm 我不这么认为,不是在 sql-server 2005 上。即使值相同,max 也只会返回一个值。 (这就是 max() 技巧可以将其他常量字段的列添加到聚合查询的原因 这很接近,但 MandoMando 是正确的,相同的设备序列号和日期时间有重复的位置。该表的 PK 由 device_serial、datetime、triggerID、latitude 和 longitude 列组成。 对不起,我明白你的意思了。是的,只需将唯一列表添加到内部选择中,并在其周围加上 max() 并将其包含在连接中即可解决您的问题【参考方案3】:您有一个正确的连接,因此如果您在表GPSReport
中有超过 1 条设备序列号记录,它将获取所有这些记录并连接到从SELECT DISTINCT device_serial FROM GPSReport
收到的唯一列表中。
【讨论】:
【参考方案4】:尝试:
Select r.*
From GPSReport r
Where datetime =
(Select Max(DateTime)
From GPSReport
Where device_serial = r.device_serial)
【讨论】:
【参考方案5】:这样的事情怎么样 - 因为我无法运行它,我希望我的 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
如果有多个具有相同的device_serial和datetime,您可能需要修改order by子句以选择首选记录
【讨论】:
【参考方案6】:我会使用公用表表达式 (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
【讨论】:
【参考方案7】:在 *** 上尝试了所有可能的答案后,我发现了这个惊人的结果
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
【讨论】:
这正是我对 MSSQL 所需要的!【参考方案8】:这是最终结果,不要使用 distinct ,因为这是新查询,它对所有 "select * FROM tbl GROUP BY bandsupported" 都有帮助。它的工作与不同的文件相同并获取所有行
【讨论】:
【参考方案9】:以下适用于 Postgresql 9+。
这些答案都不适合我(但这是 Google 为我的搜索返回的第一个链接)。我只需要获取给定表达式计算结果为等于的每组行的第一行,同时删除其他行而不使用任何聚合。
This answer 向我展示了如何使用 DISTINCT ON
(与 DISTINCT
不同):
SELECT DISTINCT ON(x,y) z, k, r, t, v
FROM foo;
在这种情况下,只采用第一个 z
。其余的 z
s 将从集合中丢弃。
您可以只选择一列(这是我所做的),而不是示例中的两列。
请记住,由于没有 GROUP BY
,因此您不能在该查询中使用真正的聚合。
查看链接中的答案以获取更多选项。写得很透彻。
【讨论】:
以上是关于在一列上选择 DISTINCT,返回多个其他列(SQL Server)的主要内容,如果未能解决你的问题,请参考以下文章
在 id 上选择 distinct 以返回一行,但能够访问其他列值(rails 关联)