2013-02-12 69 views
-1

我有5個表:位置,收費,資源,名冊和SpecialRoster。從RosterResource獲取用戶ID表

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) 

我需要構建一個報告,顯示在不同的日子Charge.TotalAmount的總和,通過資源ID。

費只有一個用戶名,但是規則很簡單:如果日期和資源ID在SpecialRoster時,用戶名是從SpecialRoster 採取如果不是,對於資源和RosterDay的日期的用戶名取 從名單當前在當時

基本上,我需要映射ResourceID,通過用戶名從名冊或SpecialRoster,充電。

的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 

回答

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和指定的任何其他表之間的聯繫。如果有一個,你只是忘了提及它,請讓我知道,如果你需要任何幫助將必要的條件(S)納入腳本。

+0

謝謝,這看起來比我寫的解決方案更好。我明天就試試看,並告訴你我該怎麼走。非常感謝你花時間陪伴。 位置表與Charge相關聯,但爲了所有意圖和目的,我忽略了它和大約120個其他字段來簡化問題 - locationID只能由報告工具提供。乾杯! – Molloch 2013-02-14 11:04:03