简体   繁体   中英

SQL Date Query include month even if no data

I have a booking database with various dates for each booking. I want to get a count of all bookings in each month eg

JAN | 12
FEB | 15
MAR | 53
APR | 25

If I have zero bookings in a month, how can I still get the month listed? eg:

JAN | 12
FEB | 15
MAR | 53
APR | 0
MAY | 52

Schema:

ID | BookingDate | REF

I don't have or want to have a months table to join against.

Below is my query so far:

SELECT TOP 1000 [Id]
  ,[MemberId]
  ,[LocationId]
  ,[Date]
  ,[BookingStateId]
  ,[RPEFeeling]
  ,[RPEPush]
  ,[Notes]
  ,[TimeSlotId]
  ,[MembershipId]
  ,[TrialSession]
  ,[CreatedDate]
  ,[ModifiedDate]
  ,[CreatedBy]
  ,[ModifiedBy]
  FROM [DB].[dbo].[SessionBooking]

DECLARE @months TABLE (MonthNumber INT, YearNumber INT, Name VARCHAR(50))
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (1, 2014, 'Jan')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (2, 2014, 'Feb')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (3, 2014, 'Mar')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (4, 2014, 'Apr')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (5, 2014, 'May')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (6, 2014, 'Jun')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (7, 2014, 'Jul')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (8, 2014, 'Aug')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (9, 2014, 'Sept')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (10, 2014, 'Oct')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (11, 2014, 'Nov')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (12, 2014, 'Dec')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (1, 2015, 'Jan')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (2, 2015, 'Feb')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (3, 2015, 'Mar')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (4, 2015, 'Apr')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (5, 2015, 'May')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (6, 2015, 'Jun')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (7, 2015, 'Jul')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (8, 2015, 'Aug')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (9, 2015, 'Sept')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (10, 2015, 'Oct')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (11, 2015, 'Nov')
INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (12, 2015, 'Dec')

SELECT MonthNumber, YearNumber, SUM(Id) 
FROM SessionBooking b
RIGHT JOIN @months mo ON DATEPART(m, b.Date) = mo.MonthNumber 
       AND DATEPART(yy, b.Date) = mo.YearNumber
GROUP BY mo.MonthNumber, mo.YearNumber

This is only returning the following results (where there are multiple bookings over last two years on each month.

MonthNumber YearNumber  (No column name)
1   2014    NULL
2   2014    NULL
3   2014    NULL
4   2014    NULL
5   2014    NULL
6   2014    NULL
7   2014    NULL
8   2014    NULL
9   2014    NULL
10  2014    NULL
11  2014    NULL
12  2014    NULL
1   2015    NULL
2   2015    215
3   2015    134
4   2015    NULL
5   2015    NULL
6   2015    NULL
7   2015    NULL
8   2015    NULL
9   2015    NULL
10  2015    NULL
11  2015    NULL
12  2015    NULL

You need to have a table variable with all the months and do a JOIN.

DECLARE @months TABLE (MonthNumber INT, YearNumber INT, Name VARCHAR(50))

INSERT INTO @months (MonthNumber, YearNumber, Name) VALUES (1, 2015, 'January')
...


SELECT MonthNumber, YearNumber, ISNULL(SUM(...), 0)
FROM Booking b
RIGHT JOIN @months mo ON DATEPART(m, b.BookingDate)=mo.MonthNumber AND DATEPART(yy, b.BookingDate)=mo.YearNumber
GROUP BY mo.MonthNumber, mo.YearNumber

EDIT: If you want to consider multiple years, add year as a column in @month and change the CROSS JOIN condition to consider month and year.

The easy way is using a months table because you can have empty months.

create table months (
   month_id integer,
   date_ini datetime,
   date_end datetime
) 

And this are some examples of how create that table automatic

Using select Generate days from date range

This use store procedure in MSQL

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM