【问题标题】:SELECT DISTINCT on one column, return multiple other columns (SQL Server)在一列上选择 DISTINCT,返回多个其他列(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 列组成。

标签: sql sql-server sql-server-2005 tsql


【解决方案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】:

          在 StackOverFlow 上尝试了所有可能的答案后,我发现了这个惊人的结果

          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,因此您不能在该查询中使用真正的聚合。

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-03-16
              • 1970-01-01
              • 1970-01-01
              • 2020-02-02
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多