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 の計算は少し複雑です。日数は、文字通り 1 か月あたり 30 日ではなく、AdmissionDate (admissionToDate) からカウントされます。たとえば、VISIT テーブルの最初のレコードは次のとおりです。

  • 2012年に2日間滞在04
  • 2+30 = 201205 の 32 日など...

ご提案をお寄せいただきありがとうございます...参考までに、数百の場所、数千のビスト、および 5 年間のデータがあります。

4

2 に答える 2

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);
于 2013-01-21T06:03:34.893 に答える
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

Location を追加すると CalendarMonths が重複する可能性がありますが、問題ないと思います。

編集 -

DischargeDate が AdmissionDate よりも 1 か月以上長い場合、いくつかの月の日付が欠落することに気付き、これを思いついたので、これをもう少しいじりました-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

もっとフィドル

これが役立つことを願っています。

幸運を。

于 2013-01-21T05:16:37.283 に答える