SQL - How to count records for each status in one line per day? - sql

I have a table Sales
Sales
--------
id
FormUpdated
TrackingStatus
There are several status e.g. Complete, Incomplete, SaveforLater, ViewRates etc.
I want to have my results in this form for the last 8 days(including today).
Expected Result:
Date Part of FormUpdated, Day of Week, Counts of ViewRates, Counts of Sales(complete), Counts of SaveForLater
--------------------------------------
2015-05-19 Tuesday 3 1 21
2015-05-18 Monday 12 5 10
2015-05-17 Sunday 6 1 8
2015-05-16 Saturday 5 3 7
2015-05-15 Friday 67 5 32
2015-05-14 Thursday 17 0 5
2015-05-13 Wednesday 22 0 9
2015-05-12 Tuesday 19 2 6
Here is my sql query:
select datename(dw, FormUpdated), count(ID), TrackingStatus
from Sales
where FormUpdated <= GETDATE()
AND FormUpdated >= GetDate() - 8
group by datename(dw, FormUpdated), TrackingStatus
order by datename(dw, FormUpdated) desc
I do not know how to make the next step.
Update
I forgot to mention, I only need the Date part of the FormUpdated, not all parts.

You can use SUM(CASE WHEN TrackingStatus = 'SomeTrackingStatus' THEN 1 ELSE 0 END)) to get the status count for each tracking status in individual column. Something like this. SQL Fiddle
select
CONVERT(DATE,FormUpdated) FormUpdated,
DATENAME(dw, CONVERT(DATE,FormUpdated)),
SUM(CASE WHEN TrackingStatus = 'ViewRates' THEN 1 ELSE 0 END) c_ViewRates,
SUM(CASE WHEN TrackingStatus = 'Complete' THEN 1 ELSE 0 END) c_Complete,
SUM(CASE WHEN TrackingStatus = 'SaveforLater' THEN 1 ELSE 0 END) c_SaveforLater
from Sales
where FormUpdated <= GETDATE()
AND FormUpdated >= DATEADD(D,-8,GetDate())
group by CONVERT(DATE,FormUpdated)
order by CONVERT(DATE,FormUpdated) desc

You can also use a PIVOT to achieve this result - you'll just need to complete the list of TrackingStatus names in both the SELECT and the FOR, and no GROUP BY required:
WITH DatesOnly AS
(
SELECT Id, CAST(FormUpdated AS DATE) AS DateOnly, DATENAME(dw, FormUpdated) AS DayOfWeek, TrackingStatus
FROM Sales
)
SELECT DateOnly, DayOfWeek,
-- List of Pivoted Columns
[Complete],[Incomplete], [ViewRates], [SaveforLater]
FROM DatesOnly
PIVOT
(
COUNT(Id)
-- List of Pivoted columns
FOR TrackingStatus IN([Complete],[Incomplete], [ViewRates], [SaveforLater])
) pvt
WHERE DateOnly <= GETDATE() AND DateOnly >= GetDate() - 8
ORDER BY DateOnly DESC
SqlFiddle
Also, I think your ORDER BY is wrong - it should just be the Date, not day of week.

Related

T-SQL pivot inventory aging by day range

Writing a T-SQL statement to display items in inventory broken out by day range (pivot).
For example from this inventory table:
ItemName
DateCreated
PO_ID
A
2020-10-07
0
B
2020-10-07
1
A
2020-10-22
2
A
2020-10-22
2
A
2020-10-22
2
B
2020-10-29
3
Would like to generate the bellow results (typically a pivot table), showing the number of pieces per ItemName per day range. The date used to calculate the # of days since DateCreated would be the day the report was ran or passed in as a parameter - in the example shown here, the date used is from '2020-11-07':
ItemName
0-10 days
11-20 days
21-30 days
>30 days
A
0
3
0
1
B
1
0
0
1
Not sure what would be the best way to write the statement to generate the above results?
I would use conditional aggregation:
select itemName,
sum(case when datediff(day, dateCreated, getdate()) <= 10 then 1 else 0 end) as days_0_10,
sum(case when datediff(day, dateCreated, getdate()) > 10 and
datediff(day, dateCreated, getdate()) <= 20
then 1 else 0 end) as days_11_20,
sum(case when datediff(day, dateCreated, getdate()) > 20 and
datediff(day, dateCreated, getdate()) <= 30
then 1 else 0 end) as days_21_30,
sum(case when datediff(day, dateCreated, getdate()) > 30 then 1 else 0 end) as days_31
from t
group by itemName
I would use something similar to the following query SQL Server:
SELECT *
FROM
(
SELECT [ItemName],[PO_ID],
CASE
WHEN DATEDIFF(day, DateCreated, getdate()) BETWEEN 0 AND 10 THEN '0-10 days'
WHEN DATEDIFF(day, DateCreated, getdate()) BETWEEN 11 AND 20 THEN '11-20 days'
WHEN DATEDIFF(day, DateCreated, getdate()) BETWEEN 21 AND 30 THEN '21-30 days'
ELSE '>30 days'
END AS PeriodCreated
FROM [TableName])
) src
pivot
(
COUNT(PO_ID)
FOR PeriodCreated in ([0-10 days], [11-20 days], [>30 days])
) piv

day of week function for week day aggregates

I currently have a query that reads from a table and aggregates based on category. It gives me what I need but I"m trying to add another column that looks at all records for that category/employee combo for the days of this past week. SO if the job with this query runs on Wednesday Night, it needs to get a total of all category/employee records for Monday and Tuesday Night as well.
The query:
SELECT employee,
sum(case when category = 'Shoes' and date_of_report >= current_date - 1 days then daily_total else 0 end) as Shoes_DAILY,
sum(case when category = 'Shoes' and date_of_report >= ( current date - ( dayofweek(current date) - 1 ) days ) then sum(daily_total) else 0 end) as dailyTotalWeek
from shoeTotals
where date_of_report >= current_date
group by employee;
So the third column there is what's messing me up saying function use not valid. here's what I want:
The source table has these records for this past week:
employee | daily_total | date_of_report
--------------------------------------------------
123 14 2019-08-26
123 1 2019-08-27
123 56 2019-08-28
123 6 2019-08-29
123 8 2019-08-30 * today
My desired output would get (based on employee and category) the total for today (8) and then the sum of all the employees' records for that category on each preceding weekday. Running on Monday night would only count that days records, friday night would count monday through friday's as shown above.
employee | shoes_daily | dailyTotalWeek
--------------------------------------------------
123 8 85
What am I doing wrong with the dayofweek function?
You cannot nest aggregation functions. I think you simply want:
select employee,
sum(case when category = 'Shoes' and date_of_report >= current_date - 1 days
then daily_total else 0
end) as Shoes_DAILY,
sum(case when category = 'Shoes' and date_of_report >= ( current date - ( dayofweek(current date) - 1 ) days )
then daily_total else 0
end) as dailyTotalWeek
from shoeTotals
where date_of_report >= current date - ( dayofweek(current date) - 1 ) days
group by employee;

How deal with this issue in SQL with Groupby

I have this data called pdays:
id|time|date_time| type_id
1 2 2016-03-05 1
2 5 2016-03-05 1
3 3 2016-03-06 2
4 7 2016-03-07 3
5 2 2016-03-10 1
6 1 2016-03-12 3
I would like to calculate the average number of time SUM(time) for weekdays and weekends grouped by type_id
The output expect like this:
type_id| weekday_time|weekends_time
1 7 2
2 3 0
3 7 1
This is my thoughts:
First I need to extract date number from date_time; Second, identify the date number whether falls into (5,6,12,13,19,20,26,27) which are weekend numbers (note: This data presents a one month case, so I do not need to worry about the changes of weekend date numbers in next month); Finally, do the aggregation and grouping on type_id
CASE WHEN pday.date IN(5,6,12,13,19,20,26,27) THEN 'weekend' ELSE 'weekday' END
This is the case part I think I should use.
First, your output appears to be wrong. Type_id 3 has both a weekend and a weekday entry, but you show one of the output values as 0.
This should get you what you want in SQL Server and it is very close to other RDBMS's. If you update your RBDMS, I'll change:
;with cte AS (
select type_id,
CASE WHEN pday.date IN(5,6,12,13,19,20,26,27) THEN 'weekday' ELSE 'weekend' END AS day_type,
SUM(time) AS time_sum
FROM pdays
GROUP BY
type_id,
CASE WHEN pday.date IN(5,6,12,13,19,20,26,27) THEN 'weekday' ELSE 'weekend' END
)
SELECT type_id,
SUM(CASE WHEN day_type = 'weekday' THEN time_sum ELSE 0 END) AS 'weekday_time',
SUM(CASE WHEN day_type = 'weekend' THEN time_sum ELSE 0 END) AS 'weekend_time'
FROM cte
GROUP BY [type_id]

How to count different data on the basis of date for distinct users in SQL Server

I have the following schema :
Table T
|ITEM_ID| |USER_ID| | DUE_DATE |
1 1 2018-01-2
1 1 2018-01-2
1 1 2018-01-3
1 2 2018-01-2
2 1 2018-01-2
2 2 2018-01-2
What I want is to get the count of actions performed by a unique user on that particular day, one week.
This is the select query which I'm using however it does not takes care of the fact about unique user.
select ITEM_ID,
sum(case when cast(due_date as date) = cast(getdate() as date) then 1 else 0 end) as today,
sum(case when cast(due_date as date) >= cast(getdate() - 7 as date) then 1 else 0 end) as week,
sum(case when cast(due_date as date) >= dateadd(month, -1, cast(getdate() as date)) then 1 else 0 end) as month
from t
group by ITEM_ID;
How can I the select count of actions performed by a unique user on that particular day, one week.
For example : let's suppose today is 2018-01-2
So the expected result should be :
ITEM_ID, COUNT_TODAY, COUNT_TOMORROW
1 2 1
2 1 1
What I need is the unique user performing the transaction of that particular item type for that day.
That is in the above example, the user having id 1 performed the transaction of type 1 2 times on 2018-01-2. So it should be counted as 1 instead of 2.
How can I achieve this?
Is this what you want.
select USER_ID, ITEM_ID,
sum(case when cast(due_date as date) = cast(getdate() as date) then 1 else 0 end) as today,
sum(case when cast(due_date as date) >= cast(getdate() - 7 as date) then 1 else 0 end) as week,
sum(case when cast(due_date as date) >= dateadd(month, -1, cast(getdate() as date)) then 1 else 0 end) as month
from t
group by USER_ID, ITEM_ID;

Sum Based on Date

I currently have this code that I want to sum every quantity based on the year. I have written a code that I thought would sum all the charges in 2016 and 2017, but it isn't running correctly.
I added the two different types of partition by statements to test and see if either would work and they don't. When I take them out, the Annual column just shows me the quantity for that specific receipt.
Here is my current code:
SELECT
ReceiptNumber
,Quantity
,Date
,sum(CASE WHEN (Date >= '2016-01-01' and Date < '2017-01-01') THEN
Quantity
ELSE 0 END)
OVER (PARTITION BY Date)
as Annual2016
,sum(CASE WHEN (Date >= '2017-01-01' and Date < '2018-01-01') THEN
Quantity
ELSE 0 END)
OVER (PARTITION BY ReceiptNumber)
as Annual2017
FROM Table1
GROUP BY ReceiptNumber, Quantity, Date
I would like my data to look like this
ReceiptNumber Quantity Date Annual2016 Annual2017
1 5 2016-01-05 17 13
2 11 2017-04-03 17 13
3 12 2016-11-11 17 13
4 2 2017-09-09 17 13
Here is a sample of some of the data I am pulling from:
ReceiptNumber Quantity Date
1 5 2016-01-05
2 11 2017-04-03
3 12 2016-11-11
4 2 2017-09-09
5 96 2015-07-08
6 15 2016-12-12
7 24 2016-04-19
8 31 2017-01-02
9 10 2017-0404
10 18 2015-10-10
11 56 2017-06-02
Try something like this
Select
..
sum(CASE WHEN (Date >= '2016-01-01' and Date < '2017-01-01') THEN
Quantity
ELSE 0 END)
OVER () as Annual2016
sum(CASE WHEN (Date >= '2017-01-01' and Date < '2018-01-01') THEN
Quantity
ELSE 0 END)
OVER ()as Annual2017
..
Where Date >= '2016-01-01' and Date < '2018-01-01'
If you want it printed only once at the top then you should run it in a separate query like:
SELECT YEAR(Date) y, sum(Quantity) s FROM Table1 GROUP BY YEAR(Date)
and then do the main query like this:
SELECT * FROM table1
Easy, peasey ... ;-)
Your original question could also be answered with:
SELECT *,
(SELECT SUM(Quantity) FROM Table1 WHERE YEAR(Date)=2016 ) Annual2016,
(SELECT SUM(Quantity) FROM Table1 WHERE YEAR(Date)=2017 ) Annual2017
FROM table1
You need some conditional aggreation over a Window Aggregate. Simply remove both PARTITION BY as you're already filtering the year in the CASE:
SELECT
ReceiptNumber
,Quantity
,Date
,sum(CASE WHEN (Date >= '2016-01-01' and Date < '2017-01-01') THEN
Quantity
ELSE 0 END)
OVER () as Annual2016
,sum(CASE WHEN (Date >= '2017-01-01' and Date < '2018-01-01') THEN
Quantity
ELSE 0 END)
OVER () as Annual2017
FROM Table1
You probably don't need the final GROUP BY ReceiptNumber, Quantity, Date