我有5个表:位置,费用,资源,名册和SpecialRoster。
CREATE TABLE Location(
LocationID int identity,
StartDate datetime,
DaysInRoster int)
CREATE TABLE Charge(
ChargeID int identity,
TotalAmount money,
ChargeDate datetime,
UserID int)
CREATE TABLE [Resource](
ResourceID int identity,
ResourceName varchar(100))
CREATE TABLE Roster(
RosterDay int,
ResourceID int,
StartDate datetime,
EndDate datetime,
UserID int)
CREATE TABLE SpecialRoster(
RosterDate datetime,
ResourceID int,
UserID int)
我需要构建一个报告,通过ResourceID显示不同日期的Charge.TotalAmount总和。
Charge只有一个UserID,但规则相当简单: 如果日期和ResourceID在SpecialRoster中,则UserID取自SpecialRoster 如果没有,资源的UserID和日期的RosterDay取自当时的名册当前
基本上,我需要将ResourceID,通过Roster或SpecialRoster中的UserID映射到Charge。
RosterDay是名单的当前日期,可以从位置计算RosterDay = DateDiff(day, Location.RosterStartDate, GetDate()) % Location.DaysInRoster
我写了一个函数来执行此操作:
CREATE FUNCTION dbo.GetRosteredUser
(
@ResourceID int,
@Date datetime,
@LocationID int
)
RETURNS int
AS
BEGIN
DECLARE @UserID int
DECLARE @RosterOffset int
Select @UserID = UserID from SpecialRoster Where ResourceID = @ResourceID and RosterDate = @Date
If @UserID is NOT NULL
return @UserID
else
Select @RosterOffset = DATEDIFF(day, StartDate, @Date) % DaysInRoster
from Location Where LocationID = @LocationID
Select @UserID = UserID from Roster Where ResourceID = @ResourceID and RosterDay = @RosterOffset
and ( @Date between StartDate and EndDate or @Date > StartDate and EndDate is NULL)
return @UserID
END
GO
但功能不是很好,因为它很慢,只允许报告一次运行一天:
Select a.ResourceID, Name, a.UserID, Sum(c.TotalAmount ) as AmountCharged
from Charge c
left outer join (
Select ResourceID, Name,
dbo.GetUserByResourceDate(ResourceID, '1/FEB/2013', 1) as UserID
from [Resource]) a
on c.UserID = a.UserID
Where ChargeDate between '1/FEB/2013' and '2/FEB/2013'
group by a.ResourceID, Name, a.UserID
有更好的方法吗?用户希望运行此操作以比较一段时间内资源的生产率。例如:
Date ResourceID Name UserID TotalAmount
01/FEB/2013 1 Sales1 22 $1024
02/FEB/2013 1 Sales1 11 $1454
03/FEB/2013 1 Sales1 14 $1900
04/FEB/2013 1 Sales1 23 $3045
答案 0 :(得分:1)
也许,这样的事情可能会有所帮助:
SELECT
re.ResourceID,
re.ResourceName,
ch.UserID,
AmountCharged = SUM(ch.TotalAmount)
FROM
Location lo
CROSS JOIN Charge ch
CROSS APPLY (
SELECT DATEDIFF(DAY, lo.StartDate, ch.ChargeDate) % lo.DaysInRoster
) x (RosterDay)
INNER JOIN
[Resource] re
LEFT JOIN Roster ro
ON
ro.RosterDay = x.RosterDay
AND ch.ChargeDate BETWEEN ro.StartDate
AND ro.RecourceID = re.ResourceID
LEFT JOIN SpecialRoster sr
ON
sr.RosterDate = ch.ChargeDate
AND sr.RecourceID = re.ResourceID
ON
ch.UserID = ISNULL(sr.UserID, ro.UserID)
GROUP BY
re.ResourceID,
re.ResourceName,
ch.UserID
WHERE
lo.LocationID = @LocationID
AND ch.ChargeDate BETWEEN ...
;
在上面的脚本中,假设所有日期时间值实际上只是日期。
另外,我有点惊讶没有发现Location
和指定的任何其他表之间的连接。如果有一个,你只是忘了提及它,如果你需要任何帮助,请在脚本中加入必要的条件,请告诉我。