您好我遇到一个特定的SQL查询问题,问题是这样的:我有两个表,其中一个有项,目前在一个产品中,第二个是历史的变化。每次编辑一个项目时,其先前状态将保存在历史记录表中,更改的时间和日期将写入项目表的item_edited列。 如果项目被删除,则将其从项目表中删除,并将新行插入历史表中,其中项目的最后状态和删除日期将写入历史表中的item_deleted列。如果未编辑item,则item_edited的值为NULL,如果item未删除,则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)))
答案 0 :(得分: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)
答案 1 :(得分: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