【问题标题】:Get 'most recent' grouped record (with order by)获取“最近的”分组记录(按顺序排列)
【发布时间】:2021-11-04 05:18:20
【问题描述】:

我有如下查询

SELECT 
      t1.Supplier,
      t2.Product,
FROM 
      t1
INNER JOIN 
      t2 ON t1.ProductCode = t2.ProductCode
GROUP BY 
      t1.Supplier, t2.Product

在表 t1 上,还有名为“Timestamp”和“Price”的列 - 我想获取最新价格,即 SELECT Price ORDER BY Timestamp DESC。我可以使用任何聚合函数来执行此操作,还是必须是子查询?

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:

执行此操作的一种标准方法是使用ROW_NUMBER() 在源数据中创建一个附加列,以便您识别每个“分区”中的“第一行”。

WITH
  supplier_sorted AS
(
  SELECT
    *,
    ROW_NUMBER() OVER (PARTITION BY supplier, ProductCode
                           ORDER BY timestamp DESC
                      )
                        AS recency_id
  FROM
   supplier
)
SELECT
  s.Supplier,
  p.Product,
  COUNT(*)
FROM
  supplier_sorted  AS s
INNER JOIN
  product          AS p
    ON s.ProductCode = p.ProductCode
WHERE
  s.recency_id = 1
GROUP BY
  s.Supplier,
  p.Product

【讨论】:

  • 你为什么在这里使用 Count(*) ?
  • @Gudwlk - 作为使用聚合的示例。 OP 使用 GROUP BY 而不是 DISTINCT and 以 , 结束 SELECT 子句,暗示他们打算在那里放“东西”。
【解决方案2】:

你可以使用cross apply:

SELECT t2.*, t1.*
FROM t2 CROSS APPLY
     (SELECT TOP (1) t1.*
      FROM t1
      WHERE t1.ProductCode = t2.ProductCode
      ORDER BY t1.TimeStamp DESC
     ) t1;

所以,GROUP BY 是不必要的。

【讨论】:

    【解决方案3】:

    可以在 ProductCode 和 Supplier 的分区上使用 row_number() 来通过 desc 使用 Timestamp Order 来获取基于分区的最新记录。然后,您可以在不聚合的情况下在同一个查询中使用以获得所需的结果。 对于这些问题,最好使用 Windows 函数而不是 Group by。

    SELECT 
       A.Supplier
      ,A.Product
      ,A.Price
    FROM
      (
      SELECT 
         t1.Supplier,
         t2.Product,
         T1.Price,
         ROW_NUMBER () OVER ( PARTITION BY t1.Supplier,t2.Product ORDER BY  T1.[Timestamp] DESC ) AS  row_num    
       FROM   t1
        INNER JOIN t2 
          ON t1.ProductCode = t2.ProductCode
        ) AS A WHERE A.row_num = 1 
    

    使用以下添加的数据进行测试。

     CREATE TABLE t1
      ( Supplier varchar(100)
       ,ProductCode int 
       , Price Decimal (10,2)
       , [TimeStamp] datetime
      )
    
    CREATE TABLE t2
    ( 
     ProductCode int 
     ,Product varchar(100)
     )
    
      insert into t1 values ('A', 1, 100.00, GetDate())
      insert into t1 values ('A', 1, 80.00, GetDate())
      insert into t1 values ('b', 2, 190.00, GetDate())
      insert into t1 values ('b', 2, 500.00, GetDate())
    
      insert into t2 values (1, 'Pro1')
      insert into t2 values (2, 'Pro2')
      insert into t2 values (3, 'Pro3')
    

    【讨论】:

      猜你喜欢
      • 2015-12-26
      • 2018-09-07
      • 1970-01-01
      • 1970-01-01
      • 2011-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多