3

これは簡単だと思いますが、わかりません。

背景情報を次に示します。

Leases と UtilityBills という 2 つのテーブルがあります。それらは、Leases テーブルの主キー (LeaseID とも呼ばれます) を参照する UtilityBills テーブルの 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

私が理解できないのは、これら 2 つのステートメントを組み合わせて、すべてのリースについて 2 番目に新しい検針日と最新の検針日をリストするクエリを生成する方法です。私が知る限り、この状況では CROSS APPLY を使用する必要がありますが、動作させることができません。ありがとう!

4

5 に答える 5

1

同じ行に両方の日付が必要な場合は、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;

ROW_NUMBER()の代わりにRANK()関数を提案する他のいくつかの答えがここにあります。ただし、最後の2つの読み取りが同じ日に行われた場合、RANK()は予期しない結果を生成します。

于 2012-12-21T14:35:36.413 に答える
0

特定の問題については、を含めることでクエリを組み合わせることができます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

これは以前の場合に機能します。長く戻るには、より複雑なソリューションが必要です。。。しかし、それはあなたの質問ではありません。

于 2012-12-21T14:30:52.863 に答える
0

私の理解が正しければ、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
于 2012-12-21T13:10:49.763 に答える
0

これを試して:

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)
于 2012-12-21T14:31:47.810 に答える
0

これを試して

;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
于 2012-12-21T13:13:49.180 に答える