选择日期最高的行

时间:2019-01-11 08:10:20

标签: sql sql-server tsql

我有以下查询,其结果与示例中相同:

SELECT            P.IdArt, P.IdAdr, P.gDate, P.Price
FROM              dbo.T_PriceData AS P INNER JOIN
                  dbo.T_Adr AS A ON P.IdAdr = A.IdAdr INNER JOIN
                  dbo.T_Stat AS S ON A.IdStat = S.IdStat
GROUP BY          P.IdArt, P.IdAdr, P.gDate, P.Price

  IdArt  IdAdr     gDate      Price
    1     10    01/01/2018     1.25
    1     10    02/01/2018     1.17     
    1     10    03/01/2018     1.18
    2     15    01/01/2018     1.03
    2     18    10/01/2018     0.12
    3     25    12/01/2018     0.98
    3     25    28/01/2018     1.99
    4     30    15/01/2018     2.55
    5     35    08/01/2018     0.11

我想要的最终结果是:

  
      
  • 如果IdArt和IdAdr相同,则所有行中的日期都应该只有最高的一行(Case IdArt 1)
  •   
  • 如果IdArt相同,但IdAdr不同,则每个IdAdr的行都应具有最高的日期。 (案例IdArt 2)
  •   
  • 价格不影响任何事情。
  •   

所以我想要的决赛桌是:

IdArt  IdAdr     gDate      Price
1      10      03/01/2018    1.18
2      15      01/01/2018    1.03
2      18      10/01/2018    0.12
3      25      28/01/2018    1.99
4      30      15/01/2018    2.55
5      35      08/01/2018    0.11

我该怎么做? 我尝试过通过MAX(gDate)选择子句,但是,当然,我从整个数据库中仅获得了一个具有最大日期的行。

3 个答案:

答案 0 :(得分:2)

关于如何执行此操作有很多答案,但是,这可以帮助您获得所需的帮助:

SELECT TOP 1 WITH TIES
       P.IdArt,
       P.IdAdr,
       P.gDate,
       P.Price
FROM dbo.T_PriceData P
     --INNER JOIN dbo.T_Adr A ON P.IdAdr = A.IdAdr --You don't reference this in the SELECT or WHERE. Why is it here?
     --INNER JOIN dbo.T_Stat S ON A.IdStat = S.IdStat --You don't reference this in the SELECT or WHERE. Why is it here?
ORDER BY ROW_NUMBER() OVER (PARTITION BY P.IdArt, P.IdAdr ORDER BY P.gDate DESC);

编辑:如果有JOIN,以确保其他表中有行,那么根据注释,我将使用EXISTS。如果仅使用JOIN,并且仅从第一个表返回行,那么最终可能会出现重复的行。

SELECT TOP 1 WITH TIES
       P.IdArt,
       P.IdAdr,
       P.gDate,
       P.Price
FROM dbo.T_PriceData P
WHERE EXISTS (SELECT 1
              FROM dbo.T_Adr A
              WHERE P.IdAdr = A.IdAdr)
  AND EXISTS (SELECT 1
              FROM dbo.T_Stat S
              WHERE A.IdStat = S.IdStat)
ORDER BY ROW_NUMBER() OVER (PARTITION BY P.IdArt, P.IdAdr ORDER BY P.gDate DESC);

答案 1 :(得分:1)

您想要每个IdArt / IdAdr组合的最高日期。窗口函数很诱人,但最有效的方法通常是相关子查询。

您的查询仅从T_PriceData中进行选择,因此查询的其余部分(联接和group by)似乎没有必要-除非联接对数据进行过滤(这似乎不太可能是因为联接)是参考表。

所以我建议:

SELECT P.IdArt, P.IdAdr, P.gDate, P.Price
FROM dbo.T_PriceData P 
WHERE P.gDate = (SELECT MAX(P2.gDate)
                 FROM dbo.T_PriceData P2
                 WHERE P2.IdArt = P.IdArt AND
                       P2.IAdr = P.IdAdr
                );

为了提高性能,您希望在(IdArt, IdAdr, gDate)上建立索引。

答案 2 :(得分:0)

您可以使用ROW_Number()

SELECT 
q.IdArt 
, q.IdArt
, q.IdADr   
, q.gDate
, q.Price
FROM (
SELECT 
  t.IdArt
, t.IdADr   
, t.gDate
, t.Price
, ROW_NUMBER() OVER (PARTITION BY t.IdArt, t.IdADr ORDER BY t.gDate DESC) rn
FROM dbo.T_PriceData t
) q
WHERE q.rn = 1