1

車両のリストを含むテーブル (Vehicles) があります。

VehicleID
PlateNo
CurrentDriver

車両のドライバー履歴を含むテーブル (履歴) もあります。

HistoryID
VehicleID
ReceivedDate (vehicle receiving date)
DriverName

すべての車両の修理を含む別のテーブル (Repairs) があります。

RepairID
VehicleID
RepairDate
RepairCost

SQL Server を使用し、History テーブルに基づいて、特定の DriverName の 2 つの日付間のすべての RepairCost 値を取得したいと考えています。

たとえば、2013 年 1 月 1 日から 2013 年 5 月 1 日の間に 3 台の異なる車両に割り当てられたドライバー 'John Doe' のすべての RepairCost 値を取得したいと考えています。

これまでの私のクエリは次のとおりです。

SELECT H.DriverName, R.RepairCost, R.RepairDate
  FROM Repairs AS R 
 INNER JOIN Vehicles AS V ON R.VehicleID = V.VehicleID 
 INNER JOIN History H ON H.VehicleID = V.VehicleID 
 WHERE H.DriverName = 'John' 
   AND R.RepairDate BETWEEN '01.01.2013' AND '04.01.2013'

SQL Fiddleにもいくつかのサンプル データがあります。

問題は、すべての結果を 2 回取得していることです。

後で編集:これまでの私の進捗状況:

DECLARE @Driver varchar(50),@StartDt datetime, @EndDt datetime

SELECT @Driver = 'John Doe',@StartDt = '20130101' ,@EndDt = '20130501'

;With VehicleAllocation
AS
(
SELECT h.*,h1.ChangeDate
FROM History h
OUTER APPLY (SELECT MIN(ReceivedDate) AS ChangeDate
FROM History
WHERE VehicleID = h.VehicleID
AND DriverName <> h.DriverName
AND ReceivedDate > h.ReceivedDate
)h1
WHERE h.DriverName = @Driver
)
SELECT *
FROM VehicleAllocation h
INNER JOIN Repairs r
ON r.VehicleID = h.VehicleID
WHERE DriverName = @Driver
AND RepairDate > = @StartDt
AND RepairDate < @EndDt + 1
AND RepairDate BETWEEN h.ReceivedDate AND COALESCE(h.ChangeDate,RepairDate)

「AND DriverName <> h.DriverName」という行に問題があることがわかりました。その行が役立つのはなぜですか?履歴テーブルに同じドライバー名が次々とあった場合、そのドライバー名の最後の納車日までスキップされました。

サンプルデータ:

「歴史」表

ReceivedDate  DriverName
04.11.2013    Mike
13.11.2013    Dan
15.11.2013    Dan
17.11.2013    Ryan
20.11.2013    Dan
22.11.2013    Ryan
25.11.2013    Mike
26.11.2013    Dan
29.11.2013    Ryan
04.12.2013    Dan

「修理」表

RepairDate RepairCost
05.11.2013 2615.30
14.11.2013 135.66
16.11.2013 4913.04
18.11.2013 538.92
21.11.2013 152.48
23.11.2013 5946.89
26.11.2013 3697.64
27.11.2013 734.01
30.11.2013 279.62

クエリ結果

RepairDate RepairCost
07.11.2013 380.00
14.11.2013 135.66
16.11.2013 4913.04
16.11.2013 4913.04
21.11.2013 152.48
27.11.2013 734.01

クエリ結果からわかるように、3 行目と 4 行目は同じ値/日付になっています。クエリ間隔は 2013 年 1 月 1 日 <-> 2013 年 12 月 31 日でした。

また、異なるテーブルから異なる列の SUM を取得したい場合はどうすればよいでしょうか? たとえば、「Repairs」テーブルの SUM(Total) 列、「Tires」テーブルの SUM(Value) 列などです。

スクリプトをどのように適応させることができますか?

ありがとう!

4

2 に答える 2

2

そこからの情報が必要ないため、クエリに Vehicle テーブルを含める理由がわかりません。

すべての修理 (たとえば、1 月 15 日の修理) を、同じ Vehicle id is History (3 つある!) を持つすべてのレコードと照合するため、「二重」の結果が得られます。これらの一致のうち 2 つはドライブ John のためのものであるため、2 つの結果が得られます。

必要なのは、履歴テーブルによると、修理時のドライブであったドライバーのみに一致させることです!

そのため、最初に各修復日を、履歴テーブルで実際に一致する Receiveddate と照合しました。

SELECT R1.Repairdate, Max(H1.ReceivedDate) as ReceivedDate
FROM Repairs R1
JOIN History H1 
  ON R1.VehicleID=H1.VehicleID 
 AND H1.ReceivedDate < R1.RepairDate

GROUP BY R1.RepairDate

次に、結合でそのクエリを使用して、必要なデータを受け取りました。

SELECT R.RepairDate, H.DriverName, R.RepairCost 
  FROM Repairs AS R 
  JOIN History H ON R.VehicleID=H.VehicleID 
  JOIN (
       SELECT R1.Repairdate, Max(H1.ReceivedDate) as ReceivedDate
         FROM Repairs R1
         JOIN History H1 
           ON R1.VehicleID=H1.VehicleID 
          AND H1.ReceivedDate < R1.RepairDate
        GROUP BY R1.RepairDate) 
        AS H2
    ON R.Repairdate = H2.Repairdate
   AND H.ReceivedDate = H2.Receiveddate
 WHERE R.RepairDate BETWEEN '01.01.2013' AND '04.01.2013' 
   AND H.DriverName = 'John'

これにより、6 つのレコードが返されます: http://sqlfiddle.com/#!3/fcebf/62

健全性チェックとして、完全なWHERE日付と名前を省略し、選択に車両番号を含めます。

その時点で車両を運転していたドライバーの名前が記載された 14 件の修理が表示されます。履歴データに従って、その時点で車両にリンクされているドライバーが正しいことを簡単に確認できます。

DRIVERNAME  VEHICLEID   REPAIRDATE  REPAIRCOST
John    1   January, 15 2013 00:00:00+0000  10
Ryan    2   January, 18 2013 00:00:00+0000  15
Ryan    2   January, 22 2013 00:00:00+0000  15
John    1   February, 03 2013 00:00:00+0000 5
Ryan    2   February, 05 2013 00:00:00+0000 25
John    1   February, 10 2013 00:00:00+0000 10
John    2   February, 26 2013 00:00:00+0000 10
Ryan    1   March, 01 2013 00:00:00+0000    100
John    2   March, 03 2013 00:00:00+0000    30
John    2   March, 08 2013 00:00:00+0000    5
Ryan    1   March, 10 2013 00:00:00+0000    45
Ryan    1   March, 17 2013 00:00:00+0000    25
Ryan    2   March, 25 2013 00:00:00+0000    10
Ryan    2   March, 28 2013 00:00:00+0000    30
于 2013-11-28T08:00:41.920 に答える