4

ActionテーブルのMOSTRECENTStatusIDデータを表示するクエリを作成しようとしています。

私のデータベースは次のようになります(SQL Server 2008のスクリーンショット):

スクリーンショット

RequestID私のサンプルデータから、アクションテーブルに#26の2つのエントリが含まれていることがわかります。StatusID(フィールドに基づいて)最新の値のみを表示したいDateStamp

スクリーンショット2

データベースのビューを作成しました。それは見た目が悪く、私のSQL書き込み能力にぶつかります。

SELECT
  P.ID AS PacketID, R.ID AS RequestID, A.ID AS ActionID, A.EmpID, P.DateStamp,
  RQ.Description AS RequestType, L.Description AS Line, R.PartNo, R.Workorder,
  R.Qty, RZ.Description AS ReasonType, R.MTF, S.Description AS Status
FROM Packet AS P
  LEFT OUTER JOIN Request AS R ON R.PacketID = P.ID
  INNER JOIN Action AS A ON A.RequestID = R.ID
  INNER JOIN RequestType AS RQ ON R.RequestTypeID = RQ.ID
  INNER JOIN Line AS L ON R.LineID = L.ID
  INNER JOIN ReasonType AS RZ ON R.ReasonTypeID = RZ.ID
  INNER JOIN Status AS S ON A.StatusID = S.ID

ただし、このビューにはすべての値が表示されているため、特定のアクションの最新の行のみをプルするために必要です。

これを行うためにビューを変更するにはどうすればよいですか?

4

5 に答える 5

1

RequestIDでグループ化された最大DateStampを取得するActionテーブルから派生テーブルを作成できます(これにより、各RequestIDの最新のDateStampが得られます)。派生テーブルを取得したら、特定のRequestIDに一致する最新のDateStampを持つアクションテーブルの行のアクションテーブルに結合し直すことができます。

SELECT
P.ID AS PacketID, R.ID AS RequestID, A.ID AS ActionID, A.EmpID, P.DateStamp,
RQ.Description AS RequestType, L.Description AS Line, R.PartNo, R.Workorder,
R.Qty, RZ.Description AS ReasonType, R.MTF, S.Description AS Status
FROM Packet AS P
LEFT OUTER JOIN Request AS R ON R.PacketID = P.ID

INNER JOIN
(SELECT RequestID, MAX(DateStamp) AS MostRecentDateStamp
 FROM Action GROUP BY RequestID) AS MostRecentAction
ON R.ID = MostRecentAction.RequestID

INNER JOIN Action AS A 
ON 
MostRecentAction.RequestID = A.RequestID
AND
MostRecentAction.MostRecentDateStamp = A.DateStamp

INNER JOIN RequestType AS RQ ON R.RequestTypeID = RQ.ID
INNER JOIN Line AS L ON R.LineID = L.ID
INNER JOIN ReasonType AS RZ ON R.ReasonTypeID = RZ.ID
INNER JOIN Status AS S ON A.StatusID = S.ID

または、別のオプションは、ここでKarwin氏が示したアプローチを取ることです 。MySQLのテーブルから単一の行を結合します。

SELECT
P.ID AS PacketID, R.ID AS RequestID, A.ID AS ActionID, A.EmpID, P.DateStamp,
RQ.Description AS RequestType, L.Description AS Line, R.PartNo, R.Workorder,
R.Qty, RZ.Description AS ReasonType, R.MTF, S.Description AS Status
FROM Packet AS P
LEFT OUTER JOIN Request AS R ON R.PacketID = P.ID

INNER JOIN Action AS A 
ON 
R.ID = A.RequestID

LEFT JOIN Action AS A2
ON
A.RequestID = A2.RequestID
AND
A.DateStamp < A2.DateStamp

INNER JOIN RequestType AS RQ ON R.RequestTypeID = RQ.ID
INNER JOIN Line AS L ON R.LineID = L.ID
INNER JOIN ReasonType AS RZ ON R.ReasonTypeID = RZ.ID
INNER JOIN Status AS S ON A.StatusID = S.ID

WHERE A2.RequestID IS NULL

私はカーウィン氏が使用するアプローチが好きです。特に、あなたが持っているような構造との関係を扱うときはそうです。

SELECT
P.ID AS PacketID, R.ID AS RequestID, A.ID AS ActionID, A.EmpID, P.DateStamp,
RQ.Description AS RequestType, L.Description AS Line, R.PartNo, R.Workorder,
R.Qty, RZ.Description AS ReasonType, R.MTF, S.Description AS Status
FROM Packet AS P
LEFT OUTER JOIN Request AS R ON R.PacketID = P.ID

INNER JOIN Action AS A 
ON 
R.ID = A.RequestID

LEFT JOIN Action AS A2
ON
A.RequestID = A2.RequestID
AND
(A.DateStamp < A2.DateStamp OR (A.DateStamp = A2.DateStamp AND A1.RequestID < A2.RequestID))

INNER JOIN RequestType AS RQ ON R.RequestTypeID = RQ.ID
INNER JOIN Line AS L ON R.LineID = L.ID
INNER JOIN ReasonType AS RZ ON R.ReasonTypeID = RZ.ID
INNER JOIN Status AS S ON A.StatusID = S.ID

WHERE A2.RequestID IS NULL
于 2012-10-05T22:27:37.397 に答える
1

これは機能します。

WITH MaxDate AS
(
   SELECT RequestID, Max(DateStamp) AS MaxDate
   FROM Action
   GROUP BY RequestID
), ActionFiltered AS
(
   SELECT Action.* 
   FROM Action
   JOIN MaxDate ON Action.RequestID=MaxDate.RequestID AND Action.DateStamp = MaxDate.MaxDate
)
SELECT
    P.ID AS PacketID, R.ID AS RequestID, A.ID AS ActionID, A.EmpID, P.DateStamp,
    RQ.Description AS RequestType, L.Description AS Line, R.PartNo, R.Workorder,
    R.Qty, RZ.Description AS ReasonType, R.MTF, S.Description AS Status
FROM ActionFiltered A
JOIN Request AS R ON A.RequestID = R.ID 
JOIN Packet AS P ON P.ID = R.PacketID
JOIN RequestType AS RQ ON R.RequestTypeID = RQ.ID
JOIN Line AS L ON R.LineID = L.ID
JOIN ReasonType AS RZ ON R.ReasonTypeID = RZ.ID
JOIN Status AS S ON A.StatusID = S.ID

これが私がやっていることです: まず、各 requestID について最新の日付 (MaxDate) を見つけ、次にそれらの行のアクション テーブルからすべてのデータを取得し (ActionFiltered)、最後にそれらすべてをテーブルに結合します内部結合。

潜在的な問題: アクション テーブルに同じ requestID とタイムスタンプを持つ 2 つのレコードがある場合、最終的なテーブルに 2 つの行が表示されます。

注:テストしていないので、タイプミスがあるかもしれません。

于 2012-10-06T03:27:17.490 に答える
1
SELECT
  P.ID AS PacketID, R.ID AS RequestID, A.ID AS ActionID, A.EmpID, P.DateStamp,
  RQ.Description AS RequestType, L.Description AS Line, R.PartNo, R.Workorder,
  R.Qty, RZ.Description AS ReasonType, R.MTF, S.Description AS Status
FROM Packet AS P
  LEFT OUTER JOIN Request AS R ON R.PacketID = P.ID
  INNER JOIN Action AS A ON A.RequestID = R.ID
  INNER JOIN RequestType AS RQ ON R.RequestTypeID = RQ.ID
  INNER JOIN Line AS L ON R.LineID = L.ID
  INNER JOIN ReasonType AS RZ ON R.ReasonTypeID = RZ.ID
  INNER JOIN Status AS S ON A.StatusID = S.ID
where A.StatusID = (
    select top 1 StatusID
    from Action
    where RequestID = R.ID
    order by DateStamp desc
    )
于 2012-10-05T22:20:17.337 に答える
1

通常、rank() を使用して、時間に基づいてレコードの最新バージョンを取得します。指定したキー (パーティション: この場合はリクエスト ID) に基づいて、レコードの各バージョンにランクが割り当てられます。降順で並べると、ランク 1 の行が最新です。asc で並べ替えると、ランク 1 の行が最も古い行になります。

EDIT :サブクエリで返された RequestId 列の名前を変更して、表示されていたエラーを削除しました。

SELECT
    P.ID AS PacketID, R.ID AS RequestID, A.ID AS ActionID, A.EmpID, P.DateStamp,
    RQ.Description AS RequestType, L.Description AS Line, R.PartNo, R.Workorder,
    R.Qty, RZ.Description AS ReasonType, R.MTF, S.Description AS Status
FROM Packet AS P
    LEFT OUTER JOIN Request AS R ON R.PacketID = P.ID
    INNER JOIN (
        select 
                req.ID as RequestIdForJoin
                , act.*
                , rank() over (partition by req.ID order by act.DateStamp desc) as [Rank]
            from Request as req 
                inner join Action as act on req.ID = act.RequestID
    ) as A
        on R.ID = A.RequestIdForJoin
    INNER JOIN RequestType AS RQ ON R.RequestTypeID = RQ.ID
    INNER JOIN Line AS L ON R.LineID = L.ID
    INNER JOIN ReasonType AS RZ ON R.ReasonTypeID = RZ.ID
    INNER JOIN Status AS S ON A.StatusID = S.ID         
    where A.[Rank] = 1 

重複アクションの場合: 同じタイムスタンプを持つ複数のアクションの @Hogan のシナリオが可能である場合は、次のように重複をステージングしてから削除できます。

declare @View table (
PacketID int, RequestID int, ActionID int, EmpID int, DateStamp datetime,
RequestType int, Line int, PartNo varchar(50), Workorder int, Qty int, 
ReasonType int, MTF varchar(50), Status int
)

insert into @View       
SELECT
    P.ID AS PacketID, R.ID AS RequestID, A.ID AS ActionID, A.EmpID, P.DateStamp,
    RQ.Description AS RequestType, L.Description AS Line, R.PartNo, R.Workorder,
    R.Qty, RZ.Description AS ReasonType, R.MTF, S.Description AS Status
FROM Packet AS P
    LEFT OUTER JOIN Request AS R ON R.PacketID = P.ID
    INNER JOIN (
        select 
                req.ID as RequestIdForJoin
                , act.*
                , rank() over (partition by req.ID order by act.DateStamp desc) as [Rank]
            from Request as req 
                inner join Action as act on req.ID = act.RequestID
    ) as A
        on R.ID = A.RequestIdForJoin
    INNER JOIN RequestType AS RQ ON R.RequestTypeID = RQ.ID
    INNER JOIN Line AS L ON R.LineID = L.ID
    INNER JOIN ReasonType AS RZ ON R.ReasonTypeID = RZ.ID
    INNER JOIN Status AS S ON A.StatusID = S.ID         
    where A.[Rank] = 1  

-- Removing all but one duplicate
;with dups as (
    select 
        RequestID
        ,row_number() over (partition by RequestID order by DateStamp) as [RowNumber]
    from @View
)
delete dups where [RowNumber] > 1

select * from @View
于 2012-10-06T05:14:08.610 に答える
1

目的を達成するために、結果を packetID でグループ化し、各 packetID の MAX(ID) を選択するサブクエリに参加できます。これは、ID フィールドが ID 列であり、最大の数値が常に最新であるため機能します。int (特にインデックス付き int) はタイムスタンプよりもはるかに高速に比較できるため、これはタイムスタンプで比較するよりも望ましい方法です。

SELECT
  P.ID AS PacketID, R.ID AS RequestID, A.ID AS ActionID, A.EmpID, P.DateStamp,
  RQ.Description AS RequestType, L.Description AS Line, R.PartNo, R.Workorder,
  R.Qty, RZ.Description AS ReasonType, R.MTF, S.Description AS Status
FROM Packet AS P
  LEFT OUTER JOIN (SELECT MAX(ID) as ID FROM Request GROUP BY PacketID) as UR ON P.ID = UR.ID
  INNER JOIN Request AS R ON R.PacketID = UR.ID
  INNER JOIN Action AS A ON A.RequestID = R.ID
  INNER JOIN RequestType AS RQ ON R.RequestTypeID = RQ.ID
  INNER JOIN Line AS L ON R.LineID = L.ID
  INNER JOIN ReasonType AS RZ ON R.ReasonTypeID = RZ.ID
  INNER JOIN Status AS S ON A.StatusID = S.ID
于 2012-10-06T00:50:43.360 に答える