在一列上选择 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。其余的 zs 将从集合中丢弃。

您可以只选择一列(这是我所做的),而不是示例中的两列。

请记住,由于没有 GROUP BY,因此您不能在该查询中使用真正的聚合。

查看链接中的答案以获取更多选项。写得很透彻。

【讨论】:

以上是关于在一列上选择 DISTINCT,返回多个其他列(SQL Server)的主要内容,如果未能解决你的问题,请参考以下文章

在一列上选择 DISTINCT

在一列上选择不同并返回所有其他列

在 id 上选择 distinct 以返回一行,但能够访问其他列值(rails 关联)

使用 T-SQL 中的 OVER 子句在除一列之外的所有列上选择 DISTINCT

SQL - 仅在一列上选择不同的[重复]

MYSQL 在一列上选择两个值