Always show empty weeks - sql-server

I need to be able to show all week numbers per month regardless of whether there are hours for that week or not.
Change this:
2.00 2 July
2.25 3 July
7.25 5 July
To this:
0.00 1 July
2.00 2 July
2.25 3 July
0.00 4 July
7.25 5 July
Here is the current query I am working with:
SELECT SUM(te.Hours_Bill) AS HoursBilled
, DATEPART(dd, DATEDIFF(dd, 0, te.Date_Start) / 7 * 7 ) / 7 + 1 AS HoursWeekNumber
, DATENAME(mm, te.Date_Start) AS HoursMonthName
FROM AGR_Header ah
INNER
JOIN Time_Entry te
ON te.Agr_Header_RecID = ah.AGR_Header_RecID
INNER
JOIN Company co
ON co.Company_RecID = ah.Company_RecID
WHERE (te.Date_Start >= DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) -6, 0) AND te.Date_Start <= DATEADD(mm, DATEDIFF(mm, -1, GETDATE()) -1, -1))
GROUP
BY DATEPART(dd, DATEDIFF(dd, 0, te.Date_Start) / 7 * 7 ) / 7 + 1
, DATENAME(mm, te.Date_Start)
, DATEPART(mm, te.Date_Start)
ORDER
BY DATEPART(mm, te.Date_Start) ASC
, DATEPART(dd, DATEDIFF(dd, 0, te.Date_Start) / 7 * 7 ) / 7 + 1 ASC
By default I want to show all week numbers for a month and if no results for the week, display 0.

This may help you
CREATE TABLE #t
(
hr NUMERIC(22, 6),
weekno INT,
mon VARCHAR(20)
)
INSERT INTO #t
VALUES
(2.00 , 2 , 'October'),
(2.25 , 3 , 'October'),
(7.25 , 5 , 'October')
WITH dates AS (
SELECT 1 id,datename(month,(getdate())) mon
UNION ALL
SELECT id+1, mon FROM dates WHERE id<5
)
SELECT Isnull(hr, 0) hrs,
id AS weekno,
d.mon AS [month]
FROM #t t
RIGHT JOIN dates d
ON t.mon = d.mon
AND t.weekno = d.id
output
hrs weekno month
0.000000 1 October
2.000000 2 October
2.250000 3 October
0.000000 4 October
7.250000 5 October

Related

Get current year of the 12 month with month wise count data in SQL Server?

I am creating a query to get the 12 month of name and I also want month wise count for the UserLogin. I want to show month wise report in bar chart. So I need to create a query in SQL Server. But with my query I am not getting the expected 12 month and count. I'm always getting 1 count in all month.
Here this is my query can you please help me where is mistake =>
SELECT
FORMAT(dateadd(MM, T.i, getdate()),'MMMM') AS DateColumn,
uf.TotalCount
FROM
(VALUES (-11),(-10),(-9),(-8),(-7),(-6), (-5), (-4), (-3), (-2), (-1), (0)) AS T(i)
OUTER APPLY
(SELECT
COUNT(datepart(MM, InsertDateTime)) AS TotalCount
FROM
User
WHERE
DATEDIFF(mm, InsertDateTime, DATEADD(day, T.i, GETDATE())) = 0
AND IsLogin = 1) uf
This is my data in the table:
UserId | IsLogin | InsertDateTime
-------+---------+---------------------------
1 1 2017-08-22 16:12:46.713
2 1 2017-08-22 16:50:55.789
3 1 2017-07-10 16:12:46.713
4 1 2017-07-10 16:12:46.713
5 1 2017-06-21 16:12:46.713
6 1 2017-06-04 16:12:46.713
7 1 2017-06-05 16:12:46.713
8 1 2016-09-05 16:12:46.713
9 1 2016-09-05 16:12:46.713
10 1 2016-10-05 16:12:46.713
11 1 2016-11-05 16:12:46.713
This is my current output:
DateColumn | TotalCount
------------+--------------
September 1
October 1
November 1
December 1
January 1
February 1
March 1
April 1
May 1
June 1
July 1
August 1
My expected output should be:
DateColumn | TotalCount
------------+--------------
January 0
February 0
March 0
April 0
May 0
June 3
July 2
August 2
September 0
October 0
November 0
December 0
Please tell me where is my problem in query. thanks
Can you try something like this. Live Demo
DECLARE #StartDate SMALLDATETIME, #EndDate SMALLDATETIME;
SELECT #StartDate = '20170101', #EndDate = '20171231';
;WITH d(d) AS
(
SELECT DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, #StartDate), 0))
FROM ( SELECT TOP (DATEDIFF(MONTH, #StartDate, #EndDate) + 1)
n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
FROM sys.all_objects ORDER BY [object_id] ) AS n
)
SELECT
[Month] = DATENAME(MONTH, d.d),
OrderCount = COUNT(o.UserId)
FROM d LEFT OUTER JOIN Table1 AS o
ON o.InsertDateTime >= d.d
AND o.InsertDateTime < DATEADD(MONTH, 1, d.d)
GROUP BY d.d
ORDER BY d.d;
After some modification in your code
SELECT FORMAT(dateadd(MM, T.i, getdate()),'MMMM') AS DateColumn,case when TotalCount is null then 0 else TotalCount end as TotalCount
FROM (VALUES (-11),(-10),(-9),(-8),(-7),(-6), (-5), (-4), (-3), (-2), (-1), (0)) AS T(i)
OUTER APPLY
(
SELECT distinct Count(datepart(MM,InsertDateTime)) AS TotalCount
FROM user1
WHERE Datediff(mm,InsertDateTime, dateadd(month, T.i, getdate())) = 0 and IsLogin = 1
) uf
order by DATEPART(MM,convert(datetime,FORMAT(dateadd(MM, T.i, getdate()),'MMMM') +'01 2017',110))
Output -
DateColumn TotalCount
January 0
February 0
March 0
April 0
May 0
June 3
July 2
August 2
September 0
October 0
November 0
December 0
Please modify your query something like below:
SELECT *
FROM (
SELECT FORMAT(dateadd(MM, T.i, getdate()), 'MMMM') AS DateColumn --, uf.TotalCount
FROM (
VALUES (- 11)
,(- 10)
,(- 9)
,(- 8)
,(- 7)
,(- 6)
,(- 5)
,(- 4)
,(- 3)
,(- 2)
,(- 1)
,(0)
) AS T(i)
) A
LEFT JOIN (
SELECT datename(month, calcdate) datecol
,count(*) #trxns
FROM EmployeeMTDResults
WHERE calcdate BETWEEN '2017-03-01'
AND getdate()
GROUP BY datename(month, calcdate)
) b ON (b.datecol = a.DateColumn)
Another Approach:
with cte as(select 0 as n
union all
select n+1 from cte
where n<11)
select DateColumn,isnull(cnt,0) 'TotalCount' from (
select DATENAME(MONTH,dateadd(mm,n,'2000-01-01'))DateColumn from cte)x
left join
(
select DATENAME(MONTH,InsertDateTime)DateColumn1 ,count (DATENAME(MONTH,InsertDateTime)) cnt from User t
where InsertDateTime>='2017-06-04 16:12:46.713' and InsertDateTime<=getdate()
group by DATENAME(MONTH,InsertDateTime)
) y on x.DateColumn=DateColumn1

Count number of items which hadn't been checked so far in the last x months

We have a list of items. Each item may be checked/examined one or more times in the last #FromDate to #ToDate (12 months, for example). How do we count the number of items which were checked in a month that had never been check since #FromDate and display that count monthly.
The result would look like below:
2014-05-01 00:00:00.000 1 May 2014 381
2014-06-01 00:00:00.000 2 June 2014 296
2014-07-01 00:00:00.000 3 July 2014 24
2014-08-01 00:00:00.000 4 August 2014 260
2014-09-01 00:00:00.000 5 September 2014 249
2014-10-01 00:00:00.000 6 October 2014 177
2014-11-01 00:00:00.000 7 November 2014 298
2014-12-01 00:00:00.000 8 December 2014 274
2015-01-01 00:00:00.000 9 January 2015 41
2015-02-01 00:00:00.000 10 February 2015 0
2015-03-01 00:00:00.000 11 March 2015 0
2015-04-01 00:00:00.000 12 April 2015 0
So far we could count the number of items which were checked monthly by using the following query:
;WITH d AS
(
SELECT DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, '2014-05-15'), 0)) as d, ROW_NUMBER() OVER (ORDER BY n) as rn
FROM ( SELECT TOP (DATEDIFF(MONTH, '2014-05-15', '2015-04-15') + 1)
n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
FROM sys.all_objects ORDER BY [object_id] ) AS n
)
SELECT
d.d,
d.rn,
DATENAME(MONTH, d.d) as [Month],
YEAR(d.d) as [Year],
COUNT(DISTINCT ItemNumber) AS Count
FROM d LEFT OUTER JOIN ItemCheck
ON CheckedTime >= d.d
AND CheckedTime < DATEADD(MONTH, 1, d.d)
GROUP BY d.d, d.rn
ORDER BY d.d;
However, we still can't figure out how to count the number of items which were checked say in July 2014 but had never been checked in May and June 2014.
A simple single query below would be able to display that for a particular month but that doesn't display in monthly.
select count(distinct ItemNumber) from ItemCheck
where CheckTime >= '2014-07-01' AND CheckTime < '2014-08-01' and
ItemNumber NOt in (SELECT ItemNumber FROM ItemCheck as t1 where t1.CheckTime >= '2014-05-01' AND t1.CheckTime < '2014-07-01')
order by ItemNumber
Update: The ItemCheck table looks like below:
CheckID | ItemNumber | CheckTime
1 i1 2014-05-02
2 i4 2014-06-12
3 i5 2014-07-03
4 i1 2014-08-01
5 i1 2014-08-02
6 i2 2014-09-15
7 i3 2014-10-11
Suppose you have a table called months with one column called month.
Then you could do it something along these lines:
DECLARE #date DATE
SET #date = '2014-01-01'
SELECT months.month AS currentMonth, COUNT(ItemNumber) ItemNumber from ItemCheck
CROSS JOIN months
WHERE CheckTime >= dateadd(m, months.month - 1, #date) AND CheckTime < dateadd(m, months.month, #date) and
ItemNumber NOT IN (SELECT ItemNumber FROM ItemCheck AS t1 WHERE t1.CheckTime >= DATEADD(m, months.month - 3, #date) AND t1.CheckTime < dateadd(m, months.month - 1, #date))
GROUP BY month
ORDER BY ItemNumber
You could also do it with a function, but you have to write it (function is called dbo.Split and you could write it this way: select data from dbo.Split(',', '1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12'). This way you could avoid creating another table (in-memory or a real one..)
If you want the code for dbo.Split I can provide it.

How to get the records grouping dates for a span of 3 days in SQL?

It's getting difficult to group and display records every 5 days.
Here is my data:
FLIGHT_DATE LANDINGS PILOTID COPILOTNAME MONT DPT
11/16/2013 1 A B 11 5.5
11/17/2013 1 A B 11 13
11/19/2013 1 A B 11 12.55
11/19/2013 1 A B 11 4
11/21/2013 1 A B 12 6
11/24/2013 1 A B 12 6.03
11/25/2013 1 A B 11 5.5
11/26/2013 1 A B 11 13
11/26/2013 1 A B 11 12.55
11/30/2013 1 A B 11 4
12/1/2013 1 A B 12 6
12/2/2013 1 A B 12 6.03
I want to show it as below:
Week Start Week End DPT
11/17/2013 11/21/2013 35.55
11/22/2013 11/26/2013 37.08
11/27/2013 12/1/2013 6
12/2/2013 12/6/2013 6.03
Here it is my proposed solution:
DECLARE #MinDate AS DATETIME = (SELECT MIN(flight_date) FROM flights);
WITH cte
AS
(
SELECT
flight_date, DATEDIFF(DAY, #MinDate, flight_date) AS NoDays,
DATEDIFF(DAY, #MinDate, flight_date)/5 AS NoGroup,
DPT
FROM flights
)
SELECT
DATEADD(DAY, NoGroup*5, #MinDate) AS [Week Start],
DATEADD(DAY, NoGroup*5+4, #MinDate) AS [Weed End],
SUM(DPT)
FROM cte
GROUP BY NoGroup;
The idea is to form groups of 5 days, then associate a record to a specific group based on division with 5. NoDays represents the days spent from MinDate to Flight_Date.
You can use this query. You need to specify the start date from which you want to count and the number of days in each period (which seems to be 5 in your case) but please adjust those numbers as needed.
declare #startdate date = '20131117'
declare #interval int = 5
select dateadd(dd, #interval * (o.number - 1), #startdate) WeekStart,
dateadd(dd, #interval * o.number - 1, #startdate) WeekEnd,
sum(d.DPT) DPT
from yourtable d
inner join
(select ROW_NUMBER() over (order by object_id) as number from sys.all_objects) as o
on d.FLIGHT_DATE >= dateadd(dd, #interval * (o.number - 1), #startdate)
and d.FLIGHT_DATE < dateadd(dd, #interval * o.number, #startdate)
group by o.number
order by dateadd(dd, #interval * (o.number - 1), #startdate)

How to count the number of days in a given month and in a given year in MSSQL

EmployeeID RecordID DateRecord
1 1 2/19/2013 12:00:00 AM
1 2 2/21/2013 12:00:00 AM
1 3 2/23/2013 12:00:00 AM
1 4 2/27/2013 12:00:00 AM
1 5 3/3/2013 12:00:00 AM
2 11 3/10/2013 12:00:00 AM
2 12 3/14/2013 12:00:00 AM
1 14 3/16/2013 12:00:00 AM
How can I count the number of days?
Example in February 2013 which has "19, 21, 23, 27" that should be count to "4" days .. ??
I found this method ..
SELECT DATEPART(yy, Daterecord),
DATEPART(mm, Daterecord),
DATEPART(dd, Daterecord),
COUNT(*)
FROM Records
GROUP BY DATEPART(yy, Daterecord),
DATEPART(mm, Daterecord),
DATEPART(dd, Daterecord)
and resulted to ..
2013 2 19 1
2013 2 21 1
2013 2 23 1
2013 2 27 1
2013 3 3 1
2013 3 10 1
2013 3 14 1
2013 3 16 1
it just get the specific dates but didm't count the total number of days in each month .. help me .. pls
I have change few names hopr you won't mind
WITH Emp_CTE AS (
SELECT EmployeeID ,DATEPART(yy, Daterecord) AS years,
DATEPART(mm, Daterecord) AS months
-- DATEPART(dd, Daterecord) AS days
FROM testTrial
)
SELECT COUNT(months) AS noOfMonths ,* FROM Emp_CTE GROUP BY months,EmployeeID,years
SqlFiddle
Let you try this:-
1: Find the number of days in whatever month we're currently in
DECLARE #dt datetime
SET #dt = getdate()
SELECT #dt AS [DateTime],
DAY(DATEADD(mm, DATEDIFF(mm, -1, #dt), -1)) AS [Days in Month]Solution
2: Find the number of days in a given month-year combo
DECLARE #y int, #m int
SET #y = 2012
SET #m = 2
SELECT #y AS [Year],
#m AS [Month],
DATEDIFF(DAY,
DATEADD(DAY, 0, DATEADD(m, ((#y - 1900) * 12) + #m - 1, 0)),
DATEADD(DAY, 0, DATEADD(m, ((#y - 1900) * 12) + #m, 0))
) AS [Days in Month]
If your table is called Employee then this will do the trick:
select convert(varchar, DateRecord, 112)/ 100, count(*)
from Employee
group by convert(varchar, DateRecord, 112)/ 100
Your initial query was almost right, just needed to remove the DATEPART(dd, Daterecord) from the grouping and it would work. Add in a HAVING clause to find the records from the month of February:
SELECT
DATEPART(yy, Daterecord),
DATEPART(mm, Daterecord),
COUNT(1)
FROM
Records
GROUP BY
DATEPART(yy, Daterecord),
DATEPART(mm, Daterecord)
HAVING
DATEPART(yy, eCreationTime) = 2013
AND DATEPART(mm, Daterecord) = 2
there is no 'yearmonth' in the suggested code ??
try this perhaps
select
datename(month,daterecord) as [Month]
, year(DateRecord) as [Year]
, count(distinct DateRecord ) as day_count
, count(distinct dateadd(day, datediff(day,0, DateRecord ), 0)) as daytime_count
from your_table
where ( DateRecord >= '20130201' and DateRecord < '20130301' )
group by
datename(month,daterecord)
, year(DateRecord)
note the column [daytime_count] is only required if the field [DateRecord] has times othe than 12:00 AM (i.e. it "trims off" times so you deal with dates at 12:AM)
Regarding date range selections: many people will feel that using 'between' is the solution however that isn't true and the safest most reliable method is as I shown above. Note that the higher date is 1st March, but we are asking for information that is less than the 1st March, so we don't need to worry about leap years and we don't have to worry about hours and minutes either.
see: What do BETWEEN and the devil have in common?
try this...
declare #date2 nvarchar(max)
set #date2 = (select getdate())
select DateDiff(Day,#date2,DateAdd(month,1,#date2))

TSQL: How to Split dates and count months in between

I need to split these dates by FY and get the number of months between the dates. I have the FY split answered previously at How to duplicate Rows with new entries link.
Having the following dates:-
ID Start dt End dt
2550 10/1/2010 9/30/2011
2551 8/1/2014 7/31/2015
2552 6/1/2013 5/31/2015
2553 5/10/2012 6/11/2014
I would like the following result set:
ID FY # of Months Start Dt End Dt
2550 2011 12 10/1/2010 9/30/2011
2551 2014 2 8/1/2014 9/30/2014
2551 2015 10 10/1/2014 7/31/2015
2552 2013 4 6/1/2013 9/30/2013
2552 2014 12 10/1/2013 9/30/2014
2552 2015 8 10/1/2014 5/31/2015
2553 2012 5 5/10/2012 9/30/2012
2553 2013 12 10/1/2012 9/30/2013
2553 2014 9 10/1/2013 6/11/2014
An FY is considered from Oct to Sept of the next year.
Thanks in advance!
It was a fun query to build:
declare #t table(id int, start_dt datetime, end_dt datetime)
Insert into #t(id, start_dt, end_dt) Values
(2550, '2010/10/1', '2011/9/30')
, (2551, '2014/8/1', '2015/7/31')
, (2552, '2013/6/1', '2015/5/31')
, (2553, '2012/5/10', '2014/6/11')
, (2554, '2012/5/10', '2012/11/1')
, (2555, '2012/5/10', '2012/8/11')
; with data as(
Select id, start_dt, end_dt, next_y = DATEADD(month, 9, DATEADD(year, DATEDIFF(year, 0, DATEADD(month, 3, start_dt)), 0))
From #t
), split as (
Select id, start_dt
, end_dt = case when next_y > end_dt then end_dt else DATEADD(day, -1, next_y) end
, next_y = DATEADD(year, 1, next_y)
From data as d
Union All
Select s.id
, DATEADD(day, 1, s.end_dt)
, case when DATEADD(day, -1, next_y) < t.end_dt then DATEADD(day, -1, next_y) else t.end_dt end
, next_y = DATEADD(year, 1, s.next_y)
From split as s
Inner Join #t as t on t.id = s.id
Where s.end_dt < t.end_dt
)
Select ID, FY = year(end_dt), '# of Months' = DATEDIFF(month, start_dt, end_dt)+1, 'Start Dt' = start_dt, 'End Dt' = end_dt
From split
Order by id, start_dt, end_dt

Resources