2013-01-21 60 views
3

這裏是我正在處理的內容: 我給出了一個表(訪問),其中包含以下具有示例數據的模式。按日曆月計算居住時長

VISIT

VisitNo Location AdmissionDate DischargeDate LengthOfStay 
1   A   2012-04-28  2012-05-30  32 
2   A   2012-04-20  2013-05-20  90 
3   B   2012-04-01  2012-05-01  30 
4   B   2012-05-01  2012-05-03  2 
..................................................... 

的要求是,返回的數據集是在以下的結構。按日曆月(YYYYMM)計算每個位置的總長度。

CalendarMonth TotalLengthOfStayEachMonth(AdmissionToDate) Location 
201204   xxx           x 
201205   yyyy           y 
201206   zzzz           z 
.........  ............... 

TotalLengthOfStayEachMonth的計算有點棘手。自錄取日期(admissionToDate)以來,這些日子不計算在每月30天的基礎上。例如,VISIT表中的第一條記錄具有;住宿

  • 2天201204
  • 2 + 30 = 32201205天的等等...

預先感謝您的建議...僅供參考,我們有幾百個一千個地點,五年的數據。

回答

1

雖然我更喜歡看到你想要的輸出,也許這樣的事情會幫助你開始:

SELECT 
    CONVERT(char(6), AdmissionDate, 112) as CalendarMonth , 
    SUM(DAY(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,AdmissionDate)+1,0)))-DAY(AdmissionDate)) as TotalLengthOfStayEachMonth, 
    Location 
FROM VISIT 
GROUP BY CONVERT(char(6), AdmissionDate, 112), Location 

添加位置將有可能給你複製CalendarMonths,但我認爲這是確定。

編輯 -

我這個多一點發揮各地,因爲我意識到了幾個月會錯過日期,如果DischargeDate是大於1月滿則AdmissionDate,以及與此想出了 - 它使用spt_values表:

select 
    CONVERT(char(6), AdmissionDate+v.number, 112) as CalendarMonth, 
    COUNT(*) Days, 
    Location 
from Visit t 
inner join master..spt_values v 
    on v.type='P' and v.number <= DATEDIFF(d, AdmissionDate, DischargeDate) 
group by Location, CONVERT(char(6), AdmissionDate+v.number, 112) 
order by CONVERT(char(6), AdmissionDate+v.number, 112), Location 

這是SQL Fiddle

- 另一個編輯

在審查另一個答案,並沒有真正瞭解你的情況(需要一個期望輸出),如果您想要的輸出是在4月2日天爲您的第一個記錄,那麼你只需要添加和v.number <> 0加入上面 - 很簡單,只是不確定你在詢問什麼。這應該是最簡單的解決方案:

select 
    CONVERT(char(6), AdmissionDate+v.number, 112) as CalendarMonth, 
    COUNT(*) Days, 
    Location 
from Visit t 
inner join master..spt_values v 
    on v.type='P' and v.number <= DATEDIFF(d, AdmissionDate, DischargeDate) and v.number <> 0 
group by Location, CONVERT(char(6), AdmissionDate+v.number, 112) 
order by CONVERT(char(6), AdmissionDate+v.number, 112), Location 

更多fiddle

希望這可以幫助一些。

祝你好運。

+0

請閱讀問題。這隻會給出按入場日期分組的總天數。他希望看到入學日期和出院日期之間每個月的天數 – cha

+0

請參閱編輯 - 這會比使用CTE更好地表現。祝你好運。 – sgeddes

+0

這兩個解決方案(Cha和這個)都可以工作,但是這個解決方案的性能要好得多。這就是爲什麼我把這個帖子標記爲公認的答案。感謝你們兩位。 – Thracian

1

這樣做(SQLFiddle):

with everyday (VisitNo, Location, dateOfStay) 
AS (
    SELECT VisitNo, Location, dateadd(dd, 1, AdmissionDate) 
    FROM VISIT 
    UNION ALL 
    SELECT e.VisitNo, e.Location, dateadd(dd, 1, e.dateOfStay) 
    FROM VISIT v INNER JOIN everyday e ON v.VisitNo = e.VisitNo and 
    e.dateofStay < v.DischargeDate 
) 
SELECT CONVERT(VARCHAR(7), dateofstay, 121), VisitNo, Location, count(*) 
FROM everyday 
GROUP BY CONVERT(VARCHAR(7), dateofstay, 121), VisitNo, Location 
ORDER BY 2,1 
OPTION (MAXRECURSION 500); 

如果你想按位置只,用這一個:

with everyday (VisitNo, Location, dateOfStay) 
AS (
    SELECT VisitNo, Location, dateadd(dd, 1, AdmissionDate) 
    FROM VISIT 
    UNION ALL 
    SELECT e.VisitNo, e.Location, dateadd(dd, 1, e.dateOfStay) 
    FROM VISIT v INNER JOIN everyday e ON v.VisitNo = e.VisitNo and 
    e.dateofStay < v.DischargeDate 
) 
SELECT CONVERT(VARCHAR(7), dateofstay, 121), Location, count(*) 
FROM everyday 
GROUP BY CONVERT(VARCHAR(7), dateofstay, 121), Location 
ORDER BY 2,1 
OPTION (MAXRECURSION 500);