我有以下查询,其结果与示例中相同:
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)选择子句,但是,当然,我从整个数据库中仅获得了一个具有最大日期的行。
答案 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