0

こんにちは、ある特定の SQL クエリで問題が発生しています。問題は次のようになります。2 つのテーブルがあり、1 つには現在 1 つの製品内にある項目があり、2 つ目は変更履歴です。1 つのアイテムが編集されるたびに、その前の状態が履歴テーブルに保存され、変更された日時がアイテム テーブルの item_edited 列に書き込まれます。アイテムが削除された場合、アイテム テーブルから削除され、アイテムの最後の状態で新しい行が履歴テーブルに挿入され、削除日が履歴テーブルの item_deleted 列に書き込まれます。アイテムが編集されていない場合、item_edited の値は NULL になり、アイテムが削除されていない場合、item_deleted の値は NULL になります。

特定の日付に製品の状態を返す SQL クエリを作成する必要があります (アイテムとその日付にあった番号)

テーブル

アイテム

product_Id (uniqueidentifier,null)  
item_Id (PK,bigint,not null)
item_name (varchar(200),not null)
item_number_of_items (int,null)
item_created (datetime,null)
item_created_by_person (uniqueidentifier,null)  
item_edited (datetime,null)
item_edited_by_person (uniqueidentifier,null)  

歴史

history_Id (PK,bigint,not null)
product_Id (uniqueidentifier,null)  
item_Id (PK,bigint,not null)
item_name (varchar(200),not null)
item_number_of_items (int,null)
item_created (datetime,null)
item_created_by_person (uniqueidentifier,null)  
item_edited (datetime,null)
item_edited_by_person (uniqueidentifier,null)
item_deleted (datetime,null)

これは私が今持っているものです。問題は、履歴から重複したアイテムを取得することです。たとえば、特定のアイテムの履歴に「編集」状態がさらにある場合、このクエリは選択した日付より前のすべての状態を返すため、重複したアイテムを取得します最終結果で。そして、選択した日付の前に最後に編集され、選択した日付の前に削除されておらず、アイテムテーブルにないアイテムのみを履歴から選択する条件が必要です。

    DECLARE @selectDate DATETIME 
    SET @selectDate = '2013/05/9' 
    DECLARE @Product_Id UNIQUEIDENTIFIER
    SET @Product_Id = 'AF4A8D96-2B9B-4C09-8FA3-C6BE20CFD391'

    SELECT item_Id,
           item_name,
           item_number_of_items,
           item_created,
           item_created_by_person,
           item_edited,
           item_edited_by_person
    FROM Items WHERE    product_Id=@Product_Id 
    AND FLOOR(CAST (ISNULL(item_edited,item_created) AS FLOAT)) <= FLOOR(CAST(@selectDate AS FLOAT))

    UNION ALL 

    SELECT item_Id,
           item_name,
           item_number_of_items,
           item_created,
           item_created_by_person,
           item_edited,
           item_edited_by_person
   FROM History 

   WHERE product_Id=@Product_Id 

   AND FLOOR(CAST (ISNULL(item_edited,item_created) AS FLOAT)) <= FLOOR(CAST(@selectDate AS FLOAT))
   AND (FLOOR(CAST(item_deleted AS FLOAT)) > FLOOR(CAST(@selectDate AS FLOAT)) OR item_deleted IS NULL)
   AND item_Id NOT IN (SELECT item_Id FROM item WHERE product_Id=@Product_Id 
                      AND FLOOR(CAST (ISNULL(item_edited,item_created) AS FLOAT)) <= FLOOR(CAST(@selectDate AS FLOAT)))
4

2 に答える 2

0

わかりました、実際に私を正しい方向に導いてくれてありがとう:) わかりました、これが私の解決策です:

CREATE TABLE #ITEMS_CURENTSTATE (item_Id BIGINT,
        item_name VARCHAR(100),
        item_number_of_items INT,
        item_created DATETIME,
        item_edited DATETIME,


CREATE TABLE #ITEMS_EDITED (item_Id BIGINT,
        item_name VARCHAR(100),
        item_number_of_items INT,
        item_created DATETIME,
        item_edited DATETIME,


CREATE TABLE #ITEMS_DELETED (item_Id BIGINT,
        item_name VARCHAR(100),
        item_number_of_componentns INT,
        item_created DATETIME,
        item_edited DATETIME,item_deleted DATETIME,



DECLARE @SELECTDATE DATETIME 
SET @SELECTDATE = '2013/05/29' 
DECLARE @PRODUCT_ID UNIQUEIDENTIFIER
SET @PRODUCT_ID = 'F67A7F31-6031-4213-8826-E53E1BC21337'


INSERT INTO #ITEMS_CURENTSTATE

SELECT item_Id,
    item_name,
    item_number_of_items,
    item_created,
    item_edited,
    FROM item WHERE 
PRODUCT_ID=@PRODUCT_ID 
AND FLOOR(CAST (ISNULL(item_edited,item_created) AS FLOAT)) <= FLOOR(CAST(@SELECTDATE AS FLOAT))





INSERT INTO #ITEMS_DELETED

SELECT item_Id,
        item_name,
        item_number_of_items,
        item_created,
        item_edited,item_deleted,


     FROM History WHERE PRODUCT_ID=@PRODUCT_ID AND FLOOR(CAST(item_deleted AS FLOAT)) <= FLOOR(CAST(@SELECTDATE AS FLOAT))



INSERT INTO #ITEMS_EDITED

SELECT  item_Id,
        item_name,
        item_number_of_items,
        item_created,
        item_edited,
     FROM History WHERE PRODUCT_ID=@PRODUCT_ID AND item_Id NOT IN (SELECT item_Id FROM #ITEMS_CURENTSTATE UNION ALL SELECT item_Id FROM #ITEMS_DELETED)
    AND FLOOR(CAST (ISNULL(item_edited,item_created) AS FLOAT)) <= FLOOR(CAST(@SELECTDATE AS FLOAT)) 



    SELECT * FROM #ITEMS_CURENTSTATE

   UNION ALL


    SELECT  A.item_Id,
        A.item_name,
        A.item_number_of_items,
        A.item_created,
        A.item_edited,
         FROM (SELECT item_Id,MAX(ISNULL(item_edited,CAST(0 AS DATETIME))) AS MaxEditDate FROM #ITEMS_EDITED GROUP BY item_Id) B 
        INNER JOIN #ITEMS_EDITED A ON A.item_Id=B.item_Id AND ISNULL(A.item_edited,CAST(0 AS DATETIME))=B.MaxEditDate


    DROP TABLE #ITEMS_CURENTSTATE    
    DROP TABLE #ITEMS_DELETED
    DROP TABLE #ITEMS_EDITED
于 2013-05-29T16:04:23.527 に答える
0

まず第一に、item_edited挿入や削除ではなく、編集時にのみ更新しているように聞こえます。これをなどの名前に変更し、元の挿入、編集、または削除のいずれであっても、状態が変化するたびLastModifiedに更新することをお勧めします。 それからあなたはただ書くことができます。

 Select * From History h
 Where item_edited = 
     (Select Max(item_edited)
      From History
      Where item_Id = h.item_Id
          And item_edited < @AsOfDatetime)

そうでない場合は、最初に新しい行を挿入するときに履歴テーブルにレコードを挿入していること、およびレコードを編集するたびに新しい現在の状態で新しいレコードを挿入していることを願っています。編集が行われたときの古い状態の履歴行。前者の場合、現在の状態が複製され、現在のテーブルだけでなく履歴テーブルでも常に最新の行になります。

もしそうなら、あなたは書くことができます

 Select * From History h
 Where Coalesce(item_deleted, item_edited, item_created) = 
     (Select Max(Coalesce(item_deleted, item_edited, item_created))
      From History
      Where item_Id = h.item_Id
          And item_edited < @AsOfDatetime)
于 2013-05-28T15:45:49.643 に答える