I'm trying to get total number of applications made for current day (Monday) to (Last Monday) , and Tuesday to Last week Tuesday and so on. Also, I would like to get applications made for this Month (Month to date ). Please help
I'm using SQL Server 2008 R2
Category Date Day Applications
CASS 16/09/2019 Monday 1
CASS 16/09/2019 Monday 3
RBS 16/09/2019 Monday 1
RBS 16/09/2019 Monday 3
RBS 16/09/2019 Monday 14
RBS 16/09/2019 Monday 15
CASS 23/09/2019 Monday 2
CASS 23/09/2019 Monday 1
CASS 23/09/2019 Monday 2
CASS 23/09/2019 Monday 1
CASS 23/09/2019 Monday 8
RBS 23/09/2019 Monday 3
RBS 23/09/2019 Monday 3
Output:
23/09/2019
CASS: 14
Previous week: 14-4=10
RBS: 6
Previous week: 6-33= -27
Month to date(Total aplications till date): 57
Using LEAD() function you could achieve what you looking for, have a look at following example, you may want adjust PARTITION BY clause and sub-query as per your requirements:
Query Result..
SELECT T.*,
LEAD (AppCount) OVER (PARTITION BY cDay ORDER BY weekNum) as PrevAppCount,
T.AppCount - LEAD (AppCount) OVER (PARTITION BY cDay ORDER BY weekNum)
FROM (
select Category,
datepart(week,cDate) as weekNum,
cDay,
sum (AppCount) as AppCount
from MyTable
Group by Category, Datepart(week,cDate),cDay
) AS T
You can write query like this:
;with cte as (
select *, rown = ROW_NUMBER() over(partition by category order by [Date]) from (
select category, [Date], sum(applications) appcnt from #table
group by category, [Date]
) t
)
Select case when nextweek.Category is null then curweek.Category else
curweek.Category + ' Previous week' end ,
case when nextweek.Category is not null then nextweek.appcnt - curweek.appcnt else curweek.appcnt end
from cte curweek
left join cte nextweek on curweek.rown = nextweek.rown -1
and curweek.Category = nextweek.Category
union all
select 'Month to date', sum(applications) from #table
code:
https://rextester.com/ABI84558
Related
I have a table like this
Input Table -
Date Salary
2020-01-01 00:00:00.000 2321
2020-01-02 00:00:00.000 2414
2020-01-03 00:00:00.000 2323
2020-01-04 00:00:00.000 2324
2020-01-05 00:00:00.000 2325.....so on
I have written a query but this query is only giving the sum of previous two weeks for which I have used LAG function
SELECT DATENAME(MONTH,Date) Months,
DATEPART(WEEK,Date) as WeekNo,
SUM(Salary) Salary,
WeekSalary= LAG(SUM(salary)) OVER (PARTITION BY Datepart(Month,Date) ORDER BY DATEPART(MONTH,Date))+SUM(salary)
FROM SheetTable
GROUP BY DATEPART(WEEK,Date),DATENAME(MONTH,Date)
Output:
Months Week Salary WeekSalary
January 1 9382 NULL
January 2 11681 21063
January 3 55245 66926
January 4 90939 146184
January 5 14091 105030
February 5 2352 NULL
February 6 16492 18844
February 7 16541 33033
February 8 16590 33131
February 9 16639 33229
March 10 16685 NULL
March 11 16730 33415
March 12 16779 33509
March 13 16828 33607
March 14 7227 24055
April 14 9650 NULL
April 15 7248 16898
but what if I need a column of total salary till week-
I tried this query
SELECT DATENAME(MONTH,Date) Months,
DATEPART(WEEK,Date) as WeekNo,
SUM(Salary) Salary,
TotalSalary=SUM(salary) OVER (ORDER BY Datepart(week,Date) ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
FROM SheetTable
GROUP BY DATEPART(WEEK,Date),DATENAME(MONTH,Date)
but this getting error:
Column 'SheetTable.salary' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Expected:
Months Week Salary TotalSalary
January 1 9382 9382 --Week(1)
January 2 11681 21063 --week(1+2)
January 3 55245 76308 --week(1+2+3)
January 4 90939 167247--week(1+2+3+4)...so on
You should be able to achieve what you need by using a frame like so:
SUM(SUM(salary)) OVER (ORDER BY Date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
Snowflake has the simply function Quarter(timestamp()) which returns current quarter, but wondering how to do day of QTR , all tutorials reference Postgres/ sql server.
Goal - create a date table, and show what day of the quarter it is for the next 20 years.
SELECT column1::timestamp as d,
DATE_TRUNC('QUARTER',d) as q,
DATEDIFF('day',q, d) as doq
FROM VALUES ('2019-10-30'),('2019-10-01');
gives 0 for the first day of the quarter, so if you need that to be 1 you can +1 that datadiff.
D Q DOQ
2019-10-30 00:00:00.000 2019-10-01 00:00:00.000 29
2019-10-01 00:00:00.000 2019-10-01 00:00:00.000 0
[Edit:] After re-reading your goal of a 20 year table, here is some code I have used in snowflake in the past to just that:
CREATE OR REPLACE TABLE twenty_years_of_days(date) AS
SELECT DATEADD(day, rn, CURRENT_DATE) as date,
DATE_TRUNC('QUARTER',date) as quarter,
DATEDIFF('day',quarter, date) as doq
FROM (
SELECT row_number() over(order by 1) as rn
FROM TABLE(GENERATOR(rowCount => 365*20)) v
);
I am looking to create a crosstab query for a timeclock website I've made. Currently I'm just displaying the result in a table with each day as it's own line.
This is an example of the data.
id type user time
4941 1 user1 2017-10-03 11:24:00
4954 2 user1 2017-10-03 14:43:00
4955 1 user1 2017-10-03 14:43:00
4967 2 user1 2017-10-03 16:00:00
And here is the query that calculates the data for the current week.
SELECT user as UserName, CONVERT (varchar(10), time, 101) AS Date,
SUM(
CASE WHEN type = 1
THEN - 1 * (datepart(hh , [time]) + datepart(mi , [time]) / 60.0)
ELSE datepart(hh , [time]) + datepart(mi , [time]) / 60.0 END) AS Total
FROM table WHERE (username LIKE 'user1')
and datepart(wk, [time]) = datepart(wk, GETDATE())
GROUP BY user, CONVERT (varchar(10), time, 101) ORDER BY Date DESC
This displays data just like I wanted.
UserName Date Total
user1 08/21/2019 4.316667
user1 08/20/2019 9.366666
user1 08/19/2019 8.283333
However now I want to take that data and put it into a crosstab query so I can show the weeks on each row with the daily data in columns on that row. So far I've tried using a pivot to accomplish this.
SELECT Year, Month, Week, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
FROM (SELECT DATENAME(WEEKDAY, CONVERT (varchar(10), time, 101)) DAY, DATEPART(wk, CONVERT (varchar(10), _time, 101)) as Week
, DATEPART(M, CONVERT (varchar(10), time, 101)) as Month, DATEPART(YYYY, CONVERT (varchar(10), time, 101)) as Year
, SUM(
CASE
WHEN type = 1
THEN - 1 * (datepart(hh , [time]) + datepart(mi , [time]) / 60.0)
ELSE datepart(hh , [time]) + datepart(mi , [time]) / 60.0
END) AS Total
FROM table WHERE (username LIKE 'user1')
GROUP BY CONVERT(varchar(10), time, 101) ) p
PIVOT (SUM(Total)
FOR DAY IN (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday) ) pvt
ORDER BY Year, Month, Week DESC
And I have some success. The data seems to be displaying correctly. However when I try to ORDER BY more than one variable the display order is out of whack.
Year Month Week Monday Tuesday Wednesday Thursday Friday Saturday Sunday
2017 10 40 NULL 4.600000 0.000000 NULL NULL NULL NULL
2018 3 11 0.966667 NULL NULL NULL NULL NULL 5.150000
2019 7 31 NULL NULL 8.116667 NULL NULL NULL NULL
2019 8 34 8.283333 9.366666 -7.483333 NULL NULL NULL NULL
2019 8 33 8.166667 8.266667 8.083333 8.616668 8.883334 NULL NULL
2019 8 32 8.350000 8.333333 8.466666 7.883333 7.516666 NULL NULL
2019 8 31 NULL NULL NULL 8.833334 8.000001 NULL NULL
It should be sorting by Year, Week and Month. When I do just the year it works orders fine. But If I add in Week and Month it jumbles up the data in the wrong order. What am I doing wrong? It should look like this.
Year Week Month Monday Tuesday Wednesday Thursday Friday Saturday Sunday
2019 34 8 8.283333 9.366666 -7.483333 NULL NULL NULL NULL
2019 33 8 8.166667 8.266667 8.083333 8.616668 8.883334 NULL NULL
2019 32 8 8.350000 8.333333 8.466666 7.883333 7.516666 NULL NULL
2019 31 8 NULL NULL NULL 8.833334 8.000001 NULL NULL
2019 31 7 NULL NULL 8.116667 NULL NULL NULL NULL
2018 11 3 0.966667 NULL NULL NULL NULL NULL 5.150000
2017 40 10 NULL 4.600000 0.000000 NULL NULL NULL NULL
Also, how can I sum the week value to a totals column?
Here is a weird one for you all.
I need to determine the number of days in a Month
;WITH cteNetProfit AS
(
---- NET PROFIT
SELECT DT.CreateDate
, SUM(DT.Revenue) as Revenue
, SUM(DT.Cost) as Cost
, SUM(DT.GROSSPROFIT) AS GROSSPROFIT
FROM
(
SELECT CAST([createDTG] AS DATE) as CreateDate
, SUM(Revenue) as Revenue
, SUM(Cost) as Cost
, SUM(REVENUE - COST) AS GROSSPROFIT
FROM [dbo].[CostRevenueSpecific]
WHERE CAST([createDTG] AS DATE) > CAST(GETDATE() - 91 AS DATE)
AND CAST([createDTG] AS DATE) <= CAST(GETDATE() - 1 AS DATE)
GROUP BY createDTG
UNION ALL
SELECT CAST([CallDate] AS DATE) AS CreateDate
, SUM(Revenue) as Revenue
, SUM(Cost) as Cost
, SUM(REVENUE - COST) AS GROSSPROFIT
FROM abc.PublisherCallByDay
WHERE CAST([CallDate] AS DATE) > CAST(GETDATE() - 91 AS DATE)
AND CAST([CallDate] AS DATE) <= CAST(GETDATE() - 1 AS DATE)
GROUP BY CALLDATE
) DT
GROUP BY DT.CreateDate
)
select distinct MONTH(CREATEDATE), DateDiff(Day,CreateDate,DateAdd(month,1,CreateDate))
FROM cteNetProfit
For some reason it is returning two different results for the month of March 2016 one result is 30 and the other 31(which of course is correct) I validate that the underlying data only has 31 days worth of data for the Month of March. Since Feb is a leap year can this affect the DATEDIFF function. The remaining months return the correct #.
2 29
3 31
3 30
4 30
5 31
Thanks for the input, however, I found the solution elsewhere
select Distinct MONTH(CREATEDATE), Day(EOMONTH(CreateDate))
FROM cteNetProfit
The difference comes when you hit the 2016-03-31 date. If you run the query below for 2016-03-30 and 2016-03-31, the results of adding 1 MONTH using DATEADD, in both instances, is 2016-04-30. It returns the last day of the next month.
SELECT DATEADD(MONTH,1,'2016-03-30') , DATEADD(MONTH,1,'2016-03-31')
This syntax seemed to work (courtesy of https://raresql.com/2013/01/06/sql-server-get-number-of-days-in-month/).
SELECT DAY(DATEADD(ms,-2,DATEADD(MONTH, DATEDIFF(MONTH,0,#DATE)+1,0))) AS [Current Month]
I have a sql query that is grouping rows by calendar week
select count(*),datepart(wk,mydate)
from MyTable
where mydate between '12/26/2010' and '1/8/2011'
group by datepart(wk,mydate)
The date range is two weeks but three rows come back because Jan 1 is a saturday and is the only day in the range that DATEPART returns a 1 the other dates return 53 or 2.
I want jan 1 to be grouped with the dates that return a 53, but I want it to be a generic answer not something like CASE WHEN datepart(wk,mydate) = 53 then 1 else datepart(wk,mydate) end because that will work for that specific date range not for other years.
I'm just wondering what a good solution would be
thanks in advance.
We use to choose as week of a date, the week of his last sunday (first day of the week in SQL). So, for each date, you can ask for the week of his last sunday with the following query:
select count(*),datepart(wk,mydate-DATEPART(dw,mydate)+1)
from MyTable
where mydate between '12/26/2010' and '1/8/2011'
group by datepart(wk,mydate-DATEPART(dw,mydate)+1)
Perhaps you can use iso_week instead of wk.
select count(*),datepart(iso_week,mydate)
from MyTable
where mydate between '12/26/2010' and '1/8/2011'
group by datepart(iso_week,mydate)
Sample:
declare #T table (Val datetime)
insert into #T values
('2010-12-30'),
('2010-12-31'),
('2011-01-01'),
('2011-01-02'),
('2011-01-03'),
('2011-01-04'),
('2011-01-05')
select
Val,
datepart(iso_week, Val) as ISO_WEEK
from #T
Result:
Val ISO_WEEK
----------------------- -----------
2010-12-30 00:00:00.000 52
2010-12-31 00:00:00.000 52
2011-01-01 00:00:00.000 52
2011-01-02 00:00:00.000 52
2011-01-03 00:00:00.000 1
2011-01-04 00:00:00.000 1
2011-01-05 00:00:00.000 1
Try DateDiff() instead with your start date as the date to compare.