我有一张包含以下数据的表格
CREATE TABLE Tbl
(
ID VARCHAR(20)
, Desc1 VARCHAR(30)
, BALANCE_DATE DATE
);
INSERT INTO Tbl (ID, Desc1, BALANCE_DATE)
VALUES ('ID1', 'Desc 1', '10/18/2015')
, ('ID1', 'Desc 2', '10/19/2015')
, ('ID1', 'Desc 3', '10/22/2015')
, ('ID1', 'Desc 4', GETDATE())
, ('ID2', 'Desc 1', '9/18/2015')
, ('ID2', 'Desc 2', '9/1/2015')
, ('ID2', 'Desc 3', '9/28/2015')
, ('ID2', 'Desc 4', GETDATE());
╔═════╦════════╦════════════════╗
║ ID ║ Desc1 ║ BALANCE_DATE ║
╠═════╬════════╬════════════════╣
║ ID1 ║ Desc 1 ║ 10/18/2015 ║
║ ID1 ║ Desc 2 ║ 10/19/2015 ║
║ ID1 ║ Desc 3 ║ 10/22/2015 ║
║ ID1 ║ Desc 4 ║ 11/21/2015 ║
║ ID2 ║ Desc 1 ║ 09/18/2015 ║
║ ID2 ║ Desc 2 ║ 09/01/2015 ║
║ ID2 ║ Desc 3 ║ 09/28/2015 ║
║ ID2 ║ Desc 4 ║ 11/21/2015 ║
╚═════╩════════╩════════════════╝
我需要获取当前日期以外的最新日期行。
预期产出:
╔═════╦════════╦════════════╗
║ ID1 ║ Desc 3 ║ 10/22/2015 ║
║ ID2 ║ Desc 3 ║ 9/28/2015 ║
╚═════╩════════╩════════════╝
如何查询?
答案 0 :(得分:3)
WITH cteMaxDateNotCurrent AS (
SELECT ID, MAX(BALANCE_DATE) AS MaxDate
FROM tbl
WHERE BALANCE_DATE <> CAST(GETDATE() AS DATE)
GROUP BY ID
)
SELECT mdnc.ID, t.Desc1, mdnc.MaxDate
FROM cteMaxDateNotCurrent mdnc
INNER JOIN tbl t
ON mdnc.ID = t.ID
AND mdnc.MaxDate = t.BALANCE_DATE;
答案 1 :(得分:2)
虽然Joe的回答是有用的,但我强烈建议在这种情况下使用ranking functions,你不必两次加入你的桌子,这对他们来说是一个完美的用例。这将是以下查询:
SELECT * FROM prices WHERE item IN ('item1', 'item2', 'item2', 'item3');
DECLARE @Tbl TABLE
(
ID VARCHAR(20)
, Desc1 VARCHAR(30)
, BALANCE_DATE DATE
);
INSERT INTO @Tbl (ID, Desc1, BALANCE_DATE)
VALUES ('ID1', 'Desc 1', '10/18/2015')
, ('ID1', 'Desc 2', '10/19/2015')
, ('ID1', 'Desc 3', '10/22/2015')
, ('ID1', 'Desc 4', GETDATE())
, ('ID2', 'Desc 1', '9/18/2015')
, ('ID2', 'Desc 2', '9/1/2015')
, ('ID2', 'Desc 3', '9/28/2015')
, ('ID2', 'Desc 4', GETDATE());
;WITH CTE(ID, Desc1, BALANCE_DATE, RN)
AS (
SELECT ID
, Desc1
, BALANCE_DATE
, DENSE_RANK() OVER(PARTITION BY Id ORDER BY BALANCE_DATE DESC)
FROM @Tbl
)
SELECT T.ID
, T.Desc1
, T.BALANCE_DATE
FROM CTE AS T
WHERE T.RN = 2;
此查询应始终为每个具有第二高日期的ID选取行。
如果您想在线测试,请参阅data.stackexchange.com上的构建查询。
╔═════╦════════╦═════════════════════╗
║ ID ║ Desc1 ║ BALANCE_DATE ║
╠═════╬════════╬═════════════════════╣
║ ID1 ║ Desc 3 ║ 2015-10-22 00:00:00 ║
║ ID2 ║ Desc 3 ║ 2015-09-28 00:00:00 ║
╚═════╩════════╩═════════════════════╝
INSERT INTO @Tbl (ID, Desc1, BALANCE_DATE)
VALUES ('ID1', 'Desc 1', '10/18/2015')
, ('ID1', 'Desc 2', '10/19/2015')
, ('ID1', 'Desc 3', '10/22/2015')
, ('ID1', 'Desc 4', GETDATE())
, ('ID2', 'Desc 1', '9/18/2015')
, ('ID2', 'Desc 2', '9/1/2015')
, ('ID2', 'Desc 3', '9/28/2015')
, ('ID2', 'Desc 4', GETDATE())
, ('ID3', 'Desc 1', '10/18/2015')
, ('ID3', 'Desc 2', '10/15/2015');
;WITH CTE(ID, Desc1, BALANCE_DATE, RN)
AS (
SELECT ID
, Desc1
, BALANCE_DATE
, DENSE_RANK() OVER(PARTITION BY Id ORDER BY BALANCE_DATE DESC)
FROM @Tbl
WHERE BALANCE_DATE < CONVERT(DATE, GETDATE())
)
SELECT T.ID
, T.Desc1
, T.BALANCE_DATE
FROM CTE AS T
WHERE T.RN = 1;