[英]SQL Server: combine maximum result and second largest results in single query
我认为这应该很容易,但我无法弄清楚。
以下是一些背景信息:
我有两个表,称为Leases和UtilityBills。 它们通过UtilityBills表中名为LeaseID的外键连接,该表引用Leases表中的主键(也称为LeaseID)。
所以这很简单 - 我正在记录每个租约的每月电表读数。
在UtilityBills表中,我有一个名为MeterReadingDate的字段,我在该字段中存储每个读表时的日期。
这是我的问题:
如何创建一个查询,为每个租约提供最新抄表日期和之前抄表日期?
使用这个sql语句,我能够轻松地获得每个租约的最新读数:
SELECT LeaseID, MAX(MeterReadingDate) AS MostRecentMeterReadingDate
FROM dbo.UtilityBills
GROUP BY LeaseID
我也可以使用这个sql语句获得任何给定租约的先前抄表(例如,这给了我先前的抄表租约LeaseID = 228):
SELECT TOP 1 MeterReadingDate, LeaseID
FROM (SELECT TOP 2 MeterReadingDate, LeaseID
FROM dbo.UtilityBills
WHERE (LeaseID = 228)
ORDER BY MeterReadingDate DESC) DERIVEDTBL
ORDER BY MeterReadingDate
我无法弄清楚的是,如何结合这两个语句来生成一个查询,列出所有租约的第二个最近和最近的抄表日期。 据我所知,我需要在这种情况下使用CROSS APPLY,但无法使其工作。 谢谢!
如果您希望两个日期位于同一行,则可以使用ROW_NUMBER()函数。 您不需要将表连接到自身,只需使用这样的组:
IF OBJECT_ID('dbo.UtilityBills') IS NOT NULL DROP TABLE dbo.UtilityBills;
CREATE TABLE dbo.UtilityBills(
Id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
LeaseId INT,
MeterReadingDate DATE
);
INSERT INTO dbo.UtilityBills(LeaseId,MeterReadingDate)VALUES
(1,'2012-01-01'),
(1,'2012-02-01'),
(1,'2012-03-01'),
(1,'2012-04-01'),
(2,'2012-01-02'),
(2,'2012-03-02'),
(2,'2012-05-02'),
(3,'2012-08-03'),
(3,'2012-10-03'),
(4,'2012-05-04');
SELECT LeaseId,
MAX(CASE WHEN rn = 1 THEN MeterReadingDate END) MostRecentReadingDate,
MAX(CASE WHEN rn = 2 THEN MeterReadingDate END) PreviousReadingDate
FROM(
SELECT LeaseID,
MeterReadingDate,
ROW_NUMBER() OVER ( PARTITION BY LeaseId ORDER BY MeterReadingDate DESC ) rn
FROM dbo.UtilityBills
)AS U
WHERE rn <=2
GROUP BY LeaseId;
这里有一些其他答案建议使用RANK()函数而不是ROW_NUMBER()。 但是,如果最后两个读数发生在同一天,RANK()将产生意外结果。
如果我理解正确,我认为您需要获取每个LeaseID的最新2个读数。 为此;
SELECT LeaseID, MeterReadingDate
FROM (
SELECT LeaseID, MeterReadingDate,
Rank() Over (Partition by LeaseID Order by MeterReadingDate desc) rk
FROM dbo.UtilityBills
) A
WHERE rk <3
ORDER BY MeterReadingDate desc
尝试这个
;WITh CTE AS
(
SELECT LEASEID, MeterReadingDate, ROW_NUMBER() OVER
(PARTITION BY LEASEID
ORDER BY MeterReadingDate DESC) RN
FROM dbo.UtilityBills
)
SELECT x1.LEASEID, x1.MeterReadingDate CurrentDate,
x2.MeterReadingDate PreviousDate
FROM CTE x1
LEFT OUTER JOIN CTE X2 ON x1.leaseid = x2.leaseid AND x1.rn + 1 = x2.rn
WHERE X1.rn = 1
对于您的特定问题,您可以通过包含group by
来组合查询。 这是一个例子:
SELECT LeaseID, MIN(MeterReadingDate) as PriorReading, MAX(MeterReadingDate) as LatestReading
FROM (SELECT TOP 2 MeterReadingDate, LeaseID
FROM dbo.UtilityBills
WHERE (LeaseID = 228)
ORDER BY MeterReadingDate DESC
) DERIVEDTBL
group by leaseid
ORDER BY MeterReadingDate
这适用于先前的。 要想更长时间,您需要一个更复杂的解决方案。 。 。 但这不是你的问题。
尝试这个:
SELECT
ls.Id as 'leaseId',
ub.MeterReadingDate as 'MeterDate'
FROM Leases ls
left outer join UtilityBills ub on ls.Id = ub.LeaseID
left outer join UtilityBills ub2 on ub2.LeaseID=ls.Id
and ub2.MeterReadingDate > ub.MeterReadingDate
left outer join UtilityBills ub3 on ub3.LeaseID=ls.Id
and ub3.MeterReadingDate > ub.MeterReadingDate
and ub3.MeterReadingDate < ub2.MeterReadingDate
left outer join UtilityBills ub4 on ub4.LeaseID=ls.Id
and ub3.Id is null
and ub4.MeterReadingDate > ub2.MeterReadingDate
WHERE ub2.Id is null
or (ub3.Id is null and ub4.Id is null)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.