鉴于这些表格:
Item
-----
Id
Description
Status
CreatedBy
ItemLog
--------
Id
ItemId
NewStatus
TimeStamp
ChangedBy
Itemlog.ItemId = Item.Id
和Status = { "Created", "Pended", "Cancelled", "Completed" }
...
如何编写SQL查询以生成以下结果:
Item Description ChangeDate NewStatus ChangedBy
1 Test1 2012-01-01 Created User1
1 Test1 2012-01-02 Pended User2
1 Test1 2012-01-03 Completed User2
2 Test2 2012-01-01 Created User2
2 Test2 2012-01-02 Pended User3
2 Test2 2012-01-09 Cancelled User1
3 Test3 2012-01-01 Created User1
3 Test3 2012-01-02 Pended User1
Item CurrentUser CurrentStatus CreatedOn TotalTime TimePended CompletedDate CancelledDate
Test1 User2 Completed 2012-01-01 3 days 1 day 2012-01-03 (null)
Test2 User1 Completed 2012-01-01 9 days 7 days (null) 2012-01-09
Test3 User1 Pended 2012-01-01 35 days 34 days (null) (null)
我希望在我的应用程序中显示为master-detail
报告。
第一个结果集是一个带有几个连接的简单查询(我没有包含UserId-UserName
表等。)
困难的部分是计算总时间......
TimeToComplete
是最后TimeStamp
的{{1}}减去第一个ItemLog
的{{1}}(其中TimeStamp
按日期排序)。
ItemLog
是每次更改状态之间ItemLog
之差的总和 - >东西。
答案 0 :(得分:2)
<强>快变!强>
create table Item(ID int, Description varchar(200),createdby varchar(20))
create table ItemLog(ID int, ItemID int, NewStatus varchar(200), [TimeStamp] datetime, ChangedBy varchar(20))
insert into Item(ID,Description,CreatedBy) values(1, 'Test 1', 'User1')
insert into Item(ID,Description,CreatedBy) values(2, 'Test 2', 'User1')
insert into Item(ID,Description,CreatedBy) values(3, 'Test 3', 'User1')
insert into ItemLog(ID, ItemID, NewStatus, TimeStamp, ChangedBy)
values(1,1,'Created','1/1/2012','User1')
insert into ItemLog(ID, ItemID, NewStatus, TimeStamp, ChangedBy)
values(2,1,'Pended','1/2/2012','User2')
insert into ItemLog(ID, ItemID, NewStatus, TimeStamp, ChangedBy)
values(3,1,'Completed','1/3/2012','User2')
insert into ItemLog(ID, ItemID, NewStatus, TimeStamp, ChangedBy)
values(4,2,'Created','1/1/2012','User2')
insert into ItemLog(ID, ItemID, NewStatus, TimeStamp, ChangedBy)
values(5,2,'Pended','1/2/2012','User3')
insert into ItemLog(ID, ItemID, NewStatus, TimeStamp, ChangedBy)
values(6,3,'Cancelled','1/9/2012','User1')
insert into ItemLog(ID, ItemID, NewStatus, TimeStamp, ChangedBy)
values(7,3,'Created','1/2/2012','User1')
insert into ItemLog(ID, ItemID, NewStatus, TimeStamp, ChangedBy)
values(8,3,'Pended','1/2/2012','User1')
select * from item i left outer join itemlog il on il.ItemID = i.ID
select
i.Description,
FirstStatusDate=minIL.TimeStamp,
CurrentStatus=maxIL.NewStatus,
CurrentStatusDate=maxIL.TimeStamp,
CurrentUser=maxIL.ChangedBy,
CompletedDate=(select max(TimeStamp) from ItemLog where ItemID=i.ID and NewStatus='Completed'),
[TotalTime (in days)]=case
when
minIL.TimeStamp is not null and maxIL.TimeStamp is not null
then datediff(day,minIL.TimeStamp,maxIL.TimeStamp)
else
convert(int,null)
end,
TimePending=sum(c.Days)
from
Item i
left outer join
(
select
y.ItemID,
y.MinDate,MinItemLogID=min(mn.id),
y.MaxDate,MaxItemLogID=max(mx.id)
from
(
select
ItemID,MinDate=min(timestamp), MaxDate=max(timestamp)
from
ItemLog il group by ItemID
) as y
left outer join ItemLog mn on mn.ItemID=y.ItemID and mn.TimeStamp=y.MinDate
left outer join ItemLog mx on mx.ItemID=y.ItemID and mx.TimeStamp=y.MaxDate
group by
y.ItemID, y.MinDate, y.MaxDate
)
z on z.ItemID = i.ID
left outer join ItemLog minIL on minIL.ID = z.MinItemLogID
left outer join ItemLog maxIL on maxIL.ID = z.MaxItemLogID
left outer join
(
select
p.ItemId,
PendTime=p.TimeStamp,
PendID=p.ID,
Days=datediff(day,p.TimeStamp,
coalesce(
(select min(TimeStamp)
from
ItemLog b
where
b.ItemID = P.ItemID and TimeStamp > p.TimeStamp )
,
getdate()
)
)
from
ItemLog p
where
p.NewStatus='Pended'
) c on c.ItemID = i.ID
group by
i.ID,
i.Description,
minIL.TimeStamp,
maxIL.NewStatus,
maxIL.TimeStamp,
maxIL.ChangedBy
答案 1 :(得分:0)
Geez ......这是否比以下内容提供了巨大的性能优势?
ALTER FUNCTION [dbo].[GetItemPendedTime]
(
-- Add the parameters for the function here
@ItemId uniqueidentifier
)
RETURNS INT
AS
BEGIN
-- Declare the return variable here
DECLARE @status INT
DECLARE @timespan datetime
DECLARE @pendTimeMinutes INT = 0
DECLARE @ispend bit = 0
DECLARE @lastTimespan datetime
DECLARE itemlog_queue CURSOR FOR
SELECT Status, Timestamp FROM ItemLog WHERE ItemId = @ItemId
OPEN itemlog_queue;
FETCH NEXT FROM itemlog_queue INTO @status, @timespan
WHILE @@FETCH_STATUS = 0
BEGIN
IF @ispend = 1
BEGIN
SET @pendTimeMinutes += DATEDIFF(minute, @lastTimespan, @timespan)
END
IF @status = 13
BEGIN
SET @ispend = 1
END
ELSE
BEGIN
SET @ispend = 0
END
SET @lastTimespan = @timespan
FETCH NEXT FROM itemlog_queue INTO @status, @timespan
END
CLOSE itemlog_queue
DEALLOCATE itemlog_queue
IF @ispend = 1
BEGIN
SET @pendTimeMinutes = @pendTimeMinutes + DATEDIFF(minute, @lastTimespan, GETDATE())
END
-- Return the result of the function
RETURN @pendTimeMinutes
END
然后将其称为
SELECT Description, Status as CurrentStatus, dbo.GetItemPendedTime(ItemId) FROM Items