I have a log table PRTL_UserAccessLog which has columns userID,datetime. I need to get the weekly distinct counts of logged users between two custom dates like the following
from date:01 Dec 2017
todate:31 dec 2017
My week start date should be from sunday.
I have created the following query to get the result
SET DATEFIRST 7
SELECT DISTINCT
'week '+ CAST(DATEPART(WEEK, Datetime)AS NVARCHAR(10)) AS weeknumber,
--I need to get the distinct count of users within this week as weekloggedcount
FROM
dbo.PRTL_UserAccessLog
WHERE
Datetime > '2017-12-01' AND Datetime < '2017-12-31'
AND usertypeid=1
ORDER BY
weeknumber
The result should be like this:
**Weeknumber** **weeklogcount**
Week48 10
Week49 50
You can try this.
SET DATEFIRST 7
SELECT DISTINCT
'week '+ CAST(DATEPART(WEEK, Datetime)AS NVARCHAR(10)) AS weeknumber,
COUNT(DISTINCT userID ) weeklogcount
FROM
dbo.PRTL_UserAccessLog
WHERE
Datetime > '2017-12-01' AND Datetime < '2017-12-31'
AND usertypeid=1
GROUP BY 'week '+ CAST(DATEPART(WEEK, Datetime)AS NVARCHAR(10))
ORDER BY weeknumber
Related
Perform a monthly distinct beneficiary count between 1/1/2018 -12/31/2020 using Microsoft SQL Server.
Below is my code but I have to change it for every month, is there any way to group by each month from 2018 to 2020 with 2 different date fields?
SELECT COUNT(distinct BEN_ID)
FROM LDS_2017andbeyond
WHERE
[DTE_FIRST_SVC] between '2018-01-01' and '2018-01-31'
AND
[DTE_LAST_SVC] between '2018-01-01' and '2018-01-31'
One simple way to group dates on the same month is the EOMONTH function. It'll return the last day of the month for a date.
SELECT
FORMAT(EOMONTH([DTE_FIRST_SVC]), 'yyyy-MM') AS MONTH_FIRST_SVC
, FORMAT(EOMONTH([DTE_LAST_SVC]), 'yyyy-MM') AS MONTH_LAST_SVC
, COUNT(DISTINCT BEN_ID) AS TOTAL_UNIQUE_BEN_ID
FROM LDS_2017andbeyond
WHERE [DTE_FIRST_SVC] BETWEEN '2018-01-01' AND '2020-12-31'
AND [DTE_LAST_SVC] BETWEEN '2018-01-01' AND '2020-12-31'
GROUP BY EOMONTH([DTE_FIRST_SVC]), EOMONTH([DTE_LAST_SVC])
ORDER BY MONTH_FIRST_SVC DESC, MONTH_LAST_SVC DESC
One solution would be to use a recursive CTE. You start with an anchor query and union it to itself with a DATEADD function in the recursive portion. This solution will give you every month month, even if the count is 0, as opposed to just grouping on the data, which will omit any months that arn't present.
Something like:
WITH CTE_Date AS (
SELECT CAST('01/01/2018' AS DATE) AS GroupMonth -- Start Date. Set as far back as necessary. Can use a DATEADD() to make dynamic.
UNION ALL
SELECT DATEADD(month, 1, GroupMonth) AS GroupMonth
FROM CTE_Date
WHERE DATEADD(month, 1, GroupMonth) < '12/31/2020' -- End Date. Remove the where to go to current.
)
SELECT
COUNT(distinct BEN_ID),
CAST(MONTH(d.GroupMonth) AS VARCHAR(2)) + '-' + CAST(YEAR(d.GroupMonth) AS VARCHAR(4)) AS Dt
FROM
LDS_2017andbeyond lds
LEFT OUTER JOIN CTE_Date d ON
MONTH(lds.[DTE_FIRST_SVC]) = MONTH(d.GroupMonth)
AND
YEAR(lds.[DTE_LAST_SVC]) = YEAR(d.GroupMonth)
GROUP BY
CAST(MONTH(d.GroupMonth) AS VARCHAR(2)) + '-' + CAST(YEAR(d.GroupMonth) AS VARCHAR(4))
I am trying to update certain fields for employees whose date of joining falls in between 10 Jun and 31 Dec, irrespective of the year. I am trying using 'Between' Operator but it requires year to be included in the dates. Is there a way to generalise it in order to consider Day and Month excluding the Year?
Use the DatePart function - replace thedate with your column, and thetable with the column.
Something like this:
select datepart(MONTH, thedate), datepart(DAY, thedate),*
from thetable
where datepart(MONTH, thedate) between 6 and 12
and datepart(DAY, thedate) between 10 and 31
You may try this:
WITH Emp AS (
SELECT *, DATEPART(MONTH, JoinDate) AS MonthJoin, DATEPART(DAY, JoinDate) AS DayJoin
FROM Employees)
SELECT *
FROM Emp
WHERE (MonthJoin > 1 AND MonthJoin < 12)
OR (MonthJoin = 1 AND DayJoin >= 10)
OR (MonthJoin = 12 AND DayJoin <= 31)
Where Employees is your table and JoinDate is your date of joining in this table
I'm not really good when it comes to database...
I'm wondering if it is possible to get the weeks of a certain month and year..
For example: 1 (January) = month and 2016 = year
Desired result will be:
week 1
week 2
week 3
week 4
week 5
This is what I have tried so far...
declare #date datetime = '01/01/2016'
select datepart(day, datediff(day, 0, #date) / 7 * 7) / 7 + 1
This only returns the total of the weeks which is 5.
declare #MonthStart datetime
-- Find first day of current month
set #MonthStart = dateadd(mm,datediff(mm,0,getdate()),0)
select
Week,
WeekStart = dateadd(dd,(Week-1)*7,#MonthStart)
from
( -- Week numbers
select Week = 1 union all select 2 union all
select 3 union all select 4 union all select 5
) a
where
-- Necessary to limit to 4 weeks for Feb in non-leap year
datepart(mm,dateadd(dd,(Week-1)*7,#MonthStart)) =
datepart(mm,#MonthStart)
Got the answer in the link: http://www.sqlservercentral.com/Forums/Topic1328013-391-1.aspx
Here is one way to approach this:
A month has a minimum of 29 or more days, and a max of 31 or less. Meaning there are almost always 5 weeks a month, with the exception of a non-leap year's feburary, and in those cases, 4 weeks a month.
You can refer to this to find out which years are "leap".
Check for leap year
Hope this helps!
The following code will allow you to select a start and end date, and output one row per week, with numbered weeks, between those dates:
declare #start date = '1/1/2016'
declare #end date = '5/1/2016'
;with cte as (select #start date
, datename(month, #start) as month
union all
select dateadd(dd, 7, date)
, datename(month, dateadd(dd, 7, date))
from CTE
where date <= #end
)
select *, 'week '
+ cast(row_number() over (partition by month order by date) as varchar(1))
from CTE
order by date
I am trying to group the number of hours that employees worked for the last 4 weeks but I want to group them on a weekly basis. For example:
WEEK HOURS
Feb 24 to March 2 55
March 3 to March 9 40
March 10 to March 16 48
March 17 to March 23 37
This is what I have so far, please help. thanks
SET DATEFIRST 1
SELECT CAST(MIN( [DT]) AS VARCHAR(20))+' TO '+CAST (MAX([DT]) AS VARCHAR(20)) AS DATE,
SUM(HOURS) AS NUM_HRS
FROM MyTable
GROUP BY DATEPART(WEEK,[DT])
HAVING COUNT(DISTINCT[DT])=7
Create a Calendar auxilliary table, with Year, Month, Week, Date columns (you can also add holidays and other interesting stuff to it, it has many potential uses) and populate it for the period of interest.
After that, it's as easy as this:
SELECT sum(hours), cast(min(date) as varchar), cast(max(date) as varchar)
FROM Calendar c
LEFT OUTER JOIN MyTable h on h.Date = c.date
GROUP BY year, week
ORDER BY year, week
SET DATEFIRST 1
SELECT DATEPART(WEEK,DT) AS WEEK,
SUM(HOURS) AS NUM_HRS
FROM MyTable
WHERE DT >= DATEADD(WEEK, -4, GetDate()),
GROUP BY DATEPART(WEEK,[DT])
Try something like
SELECT
DATEADD(DD,
CONVERT(INT, (DATEDIFF(DD, '1/1/1900', t.DT)/7)) * 7,
'1/1/1900') [WeekBeginDate],
DATEADD(DD,
(CONVERT(INT, (DATEDIFF(DD, '1/1/1900', t.DT)/7)) * 7) + 6,
'1/1/1900') [WeekEndDate],
SUM(HOURS) AS NUM_HRS
FROM MyTable t
GROUP BY CONVERT(INT, DATEDIFF(DD, '1/1/1900', t.DT)/7)
Though this is the brute force trick, I think in your case it will work.
EDIT : Modified the query a little bit, the error was caused because of the order in which DATEDIFF calculates the difference.
Also here is a SQL FIDDLE with a working example.
EDIT 2 : Updated the Fiddle with the Date Format. To customize the date format, this article would help.
For example,
the start date = '20100530' and
the end date = '20100602'
How can I write a SQL to display the below result?
month: may, 2 days
month: June, 2 days
Use a recursive CTE to generate all of the dates between the start and end, and then do a simple group and count (caution, not tested, but should be close if not exactly right):
with dates (the_date) as (
select #start_date
UNION ALL
select dateadd(dd, 1, the_date) from dates where the_date <= #end_date
)
select
datepart(mm, the_date) month,
count(*) num_days
from
dates
group by
datepart(mm, the_date)
TBH, you really need to provide more schema and information about the source data. However, given what little we know, you should be able to write:
Select DateName('month', [Date]) As Month
, Cast(DateDiff(d, #StartDate, #EndDate) As varchar(10) - 1) + ' days'
From Table
Where [Date] Between #StartDate And #EndDate
What we'd need to know to refine our solutions is exactly how 2 days is supposed to be calculated. Is it the days between the start and end date? Is it the day of the second parameter?