我有一个表转换问题。这是一个理由结果问题。
举个例子,一群幼儿园学生会读一些书。当一个学生读完他的第一本书时,应该给他一个苹果作为礼物。他永远不会得到一个以上的苹果。但是,实际上结果并不总是如设计的那样,并且可能发生错误。可能不会给予苹果,也不会在错误的时间给予苹果。
以下两个表是示例数据:
create table #Reason (Student VARCHAR(20), BookName VARCHAR(20), FinishTime DateTime)
INSERT INTO #Reason VALUES
('Student1', 'Book11', '2015-03-01 13:00:00')
,('Student1', 'Book12', '2015-03-02 10:00:00')
,('Student1', 'Book13', '2015-03-03 18:00:00')
,('Student2', 'Book21', '2015-03-01 16:00:00')
,('Student2', 'Book22', '2015-03-02 18:00:00')
,('Student2', 'Book23', '2015-03-03 18:00:00')
,('Student2', 'Book24', '2015-03-04 18:00:00')
,('Student3', 'Book31', '2015-03-01 6:00:00')
,('Student3', 'Book32', '2015-03-02 8:00:00')
,('Student3', 'Book33', '2015-03-03 9:00:00')
,('Student3', 'Book34', '2015-03-04 12:00:00')
-----------------------------------------------------
create table #Result (Student VARCHAR(20), GiftName VARCHAR(20), GiftTime DateTime)
INSERT INTO #Result VALUES
('Student1', 'Apple', '2015-03-01 13:01:00')
,('Student2', 'Apple', '2015-03-01 18:01:00')
,('Student2', 'Apple', '2015-03-03 15:01:00')
,('Student2', 'Apple', '2015-03-04 15:08:00')
,('Student2', 'Apple', '2015-03-04 15:09:00')
,('Student3', 'Apple', '2015-02-28 10:01:00')
,('Student4', 'Apple', '2015-04-28 10:01:00')
所需的输出表应该是(添加正确的列以指示是否在正确的时间给出苹果):
('Yes','Student1', 'Book11', '2015-03-01 13:00:00', 'Apple', '2015-03-01 13:01:00')
('Yes' ,'Student1', 'Book12', '2015-03-02 10:00:00', NULL , NULL )
('Yes' ,'Student1', 'Book13', '2015-03-03 18:00:00', NULL , NULL )
('Yes','Student2', 'Book21', '2015-03-01 16:00:00', 'Apple', '2015-03-01 18:01:00')
('No ','Student2', 'Book22', '2015-03-02 18:00:00', 'Apple', '2015-03-03 15:01:00')
('No ','Student2', 'Book23', '2015-03-03 18:00:00', 'Apple', '2015-03-04 15:08:00')
('No ','Student2', 'Book23', '2015-03-03 18:00:00', 'Apple', '2015-03-04 15:09:00')
('Yes' ,'Student2', 'Book24', '2015-03-04 18:00:00', NULL , NULL )
('No ','Student3', 'Book31', '2015-03-01 06:00:00', NULL , NULL )
('No ','Student3', NULL , NULL , 'Apple', '2015-02-28 10:01:00')
('Yes' ,'Student3', 'Book32', '2015-03-02 8:00:00' , NULL , NULL )
('Yes' ,'Student3', 'Book33', '2015-03-03 9:00:00' , NULL , NULL )
('Yes' ,'Student3', 'Book34', '2015-03-04 12:00:00', NULL , NULL )
('No ','Student4', NULL , NULL , 'Apple', '2015-04-28 10:01:00')
答案 0 :(得分:0)
试试这个SQL Fiddle
对于SQL Server 2008
;WITH Reason as
(
Select Student,BookName,FinishTime,ROW_NUMBER()OVER(PARTITION BY student ORDER BY FinishTime) BookNo,
(SELECT MIN(FinishTime) FROM #Reason R2 WHERE R2.Student = R1.Student AND R2.FinishTime > R1.FinishTime) Next_Finish
FROM #Reason R1
),
Reason_WithGift as
(
SELECT *
FROM Reason Rn
),
Results as
(
SELECT Student,GiftName,GiftTime,ROW_NUMBER()OVER(PARTITION BY student ORDER BY GiftTime) GiftNo
FROM #Result
)
SELECT CASE WHEN ((BookNo = 1 AND GiftNo = 1) OR(BookNo <> 1 AND GiftNo IS NULL)) THEN 'Yes' ELSE 'No' END,ISNULL(Rn.Student,Rt.Student) Student,Rn.BookName,Rn.FinishTime,Rt.GiftName,Rt.GiftTime
FROM Reason_WithGift Rn
FULL OUTER JOIN Results Rt
ON Rt.Student = Rn.Student
AND Rt.GiftTime BETWEEN Rn.FinishTime
AND ISNULL(Next_Finish,'2999/12/31')
ORDER BY ISNULL(Rn.Student,Rt.Student),Rn.BookName
对于SQL Server 2012及更高版本
;WITH Reason as
(
Select Student,BookName,FinishTime,LEAD(FinishTime)OVER(partition by student order by FinishTime) Next_Finish,ROW_NUMBER()OVER(PARTITION BY student ORDER BY FinishTime) BookNo
FROM #Reason
),
Reason_WithGift as
(
SELECT *
FROM Reason Rn
),
Results as
(
SELECT Student,GiftName,GiftTime,ROW_NUMBER()OVER(PARTITION BY student ORDER BY GiftTime) GiftNo
FROM #Result
)
SELECT IIF((BookNo = 1 AND GiftNo = 1) OR(BookNo <> 1 AND GiftNo IS NULL),'Yes','No'),ISNULL(Rn.Student,Rt.Student) Student,Rn.BookName,Rn.FinishTime,Rt.GiftName,Rt.GiftTime
FROM Reason_WithGift Rn
FULL OUTER JOIN Results Rt
ON Rt.Student = Rn.Student
AND Rt.GiftTime BETWEEN Rn.FinishTime
AND ISNULL(Next_Finish,'2999/12/31')
ORDER BY ISNULL(Rn.Student,Rt.Student),Rn.BookName
答案 1 :(得分:0)
在ughai的帮助下,我修改了查询,它确实有效。再次感谢ughaim!
但我不知道如何发布我的更改。
改变:
摆脱reason_withgift临时表
更改结果临时表,类似于原因表
使用以下内容替换where子句
中的时间条件AND Reason.FinishTime&lt; = Result.GiftTime AND Reason.Next_FinishTime&gt; = Result.GiftTime