2

次のような特定の日付範囲があります

From Date        To Date
---------------------------    
2012-11-10       2012-11-15
2012-11-21       2012-11-22
2012-11-30       2012-12-01

2 つの日付間の合計日数と特定の月の合計日数を計算する SQL クエリを作成したい

私が欲しかった出力は、

No of days     month
--------------------
   9            11
   1            12

この SQL クエリの作成を手伝ってくれる人はいますか?

4

4 に答える 4

1

理想的には、使用するすべての日付 (1950 年から 2100 年など) を含む "Dates" という名前のテーブルがあるとします。このクエリでは、必要な結果が得られます。

  select dateadd(m,datediff(m, 0, d.thedate),0) themonth, count(1)
    from dates d
    join ranges r on d.thedate between r.[from date] and r.[to date]
group by datediff(m, 0, d.thedate)
order by themonth;

結果:

|   themonth | COLUMN_1 |
-------------------------
| 2012-11-01 |        9 |
| 2012-12-01 |        1 |

「11」または「12」を月として表示するだけではなく、範囲が 12 か月を超える場合にうまく機能しないか、新しい年をまたぐ場合の並べ替えに役立たないことに注意してください。このクエリでは、最初の日が表示されます。代わりに月の。

datesそうでない場合は、以下の拡張クエリに従って、その場で仮想的にテーブルを作成できます。

;with dates(thedate) as (
  select dateadd(yy,years.number,0)+days.number
    from master..spt_values years
    join master..spt_values days
      on days.type='p' and days.number < datepart(dy,dateadd(yy,years.number+1,0)-1)
   where years.type='p' and years.number between 100 and 150
      -- note: 100-150 creates dates in the year range 2000-2050
      --       adjust as required
)
  select dateadd(m,datediff(m, 0, d.thedate),0) themonth, count(1)
    from dates d
    join ranges r on d.thedate between r.[from date] and r.[to date]
group by datediff(m, 0, d.thedate)
order by themonth;

完全な作業サンプルは次の場所にあります: SQL Fiddle

于 2012-11-28T08:05:56.837 に答える
0

これを試して

select ((day(date_to)) - (day(date_from))) as no_of_days,month(date_from)as month from tablename 
于 2012-11-28T07:47:40.763 に答える
0

SQL の書き方が悪くてすみません。
仮定は、月の違いです。fromdate と todate の間は 1 です。

スキーマ

CREATE TABLE dateData
    (fromdate datetime, todate datetime)
;

INSERT INTO dateData
    (fromdate, todate)
VALUES
    ('2012-11-10', '2012-11-15'),
    ('2012-11-21', '2012-11-22'),
    ('2012-11-30', '2012-12-01')
;

SQL

select mth, sum(days) as daysInMth
from
(
select month(fromdate) as mth,
sum(case 
when month(fromdate) = month(todate) then datediff(dd, fromdate, todate)+1
else datediff(dd, fromdate, dateadd(mm, 1, fromdate) - day(fromdate)) + 1 end)
as days 
from dateData
group by month(fromdate)
union
select month(todate) as mth,
sum(case when month(todate) <> month(fromdate) then
datediff(dd, fromdate, dateadd(mm, 1, fromdate) - day(fromdate)) + 1
else 
case when month(todate) = month(fromdate) then 0 else
datediff(dd, convert(datetime, year(todate) + '-' + month(todate) + '-1'), todate) 
end
end) as days
from dateData
group by month(todate)
) aggregated
group by mth

SQLFiddle で表示: http://www.sqlfiddle.com/#!3/9f7da/56

于 2012-11-28T07:59:18.777 に答える
0

私はそれをいくつかのステップに分割します(それぞれに個別のCTEが与えられます):

declare @Ranges table (FromDate date not null,ToDate date not null)
insert into @Ranges (FromDate,ToDate) values
('20121110','20121115'),
('20121121','20121122'),
('20121130','20121201')

;with Months as (
    select
        DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010101') as MonthStart,
        DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010131') as MonthEnd
    from @Ranges
    union /* not all */
    select
        DATEADD(month,DATEDIFF(month,'20010101',ToDate),'20010101') as MonthStart,
        DATEADD(month,DATEDIFF(month,'20010101',ToDate),'20010131') as MonthEnd
    from @Ranges
), MonthRanges as (
    select
        CASE WHEN r.FromDate > m.MonthStart then r.FromDate ELSE m.MonthStart END as StartRange,
        CASE WHEN r.ToDate < m.MonthEnd then r.ToDate ELSE m.MonthEnd END as EndRange
    from
        @Ranges r
            inner join
        Months m
            on
                r.ToDate >= m.MonthStart and
                r.FromDate <= m.MonthEnd
)
select
    DATEPART(month,StartRange),
    SUM(DATEDIFF(day,StartRange,EndRange)+1) /* Inclusive */
from
    MonthRanges
group by
    DATEPART(month,StartRange)

まず、MonthsCTE は、関心のある各月の最初と最後の日を見つけます (*)。次に、MonthRangesこのデータを元の範囲と再結合し、必要に応じて分割して、扱っている各期間が 1 か月の日数のみを表すようにします。次にDATEDIFF、各範囲にまたがる日数を計算するために使用できます (日付を扱っており、包括的な値が必要なため、1 を追加します)。

(*) MonthsCTE は、複数の月にまたがる範囲を扱っておらず、その間の月に開始または終了する他の範囲がない場合に機能します。この状況に対処する必要がある場合は、MonthsCTE を修正する必要があります。たとえば('20120115','20120315')、上記のサンプルに (他の範囲を追加せずに) 追加すると、上記を使用して 2 月の結果は得られません。この状況に対処する必要がありますか?


(*) で示されている状況に対処するためMonthsに、上記のクエリの CTE を次のように置き換えることができます。

;With LastMonth as (
    select MAX(ToDate) as Mx from @Ranges
), MultiMonths as (
    select
        DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010101') as MonthStart,
        DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010131') as MonthEnd
    from @Ranges
    union all
    select
        DATEADD(month,1,MonthStart),
        DATEADD(month,1,MonthEnd)
    from MultiMonths
    where MonthStart <= (select Mx from LastMonth)
), Months as (
    select distinct MonthStart,MonthEnd from MultiMonths 
)
于 2012-11-28T08:00:51.393 に答える