Count grouped colums and group them via other column - sql

I have a little problem.
The data:
2016-11-09 0536B088-D3DE-4C0E-903F-C2463D0AAB7E
2016-11-09 866D70EC-93FD-4C30-BC54-C7B954F255BE
2016-11-09 6C090D6B-9842-4CB0-9E10-F9B941C8D3A1
2016-11-09 FB1DD63E-F098-4191-B8F4-BEA4F9776B54
2016-11-09 FB1DD63E-F098-4191-B8F4-BEA4F9776B54
2016-11-10 0536B088-D3DE-4C0E-903F-C2463D0AAB7E
2016-11-10 NULL
2016-11-10 0536B088-D3DE-4C0E-903F-C2463D0AAB7E
2016-11-11 0536B088-D3DE-4C0E-903F-C2463D0AAB7E
2016-11-11 0536B088-D3DE-4C0E-903F-C2463D0AAB7E
From it I want to count UserId and group via Date.
I should be like this:
Date | Unique | Returning | New
..09 | 4 | 1 | 3
..10 | 2 | 1 | 1
..11 | 1 | 1 | 0
How I can do it?
I have this query.
select
cast(EventTime as date) as 'Date',
count(distinct UserId) + count(distinct case when UserId is null then 1 end) as 'Unique users',
0 as 'Returning users',
0 as 'New users'
from
TelemetryData
where
DiscountId = '5F8851DD-DF77-46DC-885E-46ECA93F021C' and EventName = 'DiscountClick'
group by
cast(EventTime as date)`
Unique users = unique with NULL too!
Returing users = UserId who clicked more than 1 times isnull(sum(case when UserId(here shoudld be count) > 1 then 1 else 0 end), 1)
New users who clicked only one! isnull(sum(case when UserId(count also) = 1 then 1 else 0 end), 1)
#EDIT:
Ok, two of your results work perfect. But I need now integrate it with other query.
SELECT
'5F8851DD-DF77-46DC-885E-46ECA93F021C',
cast([dbo].[TelemetryData].[EventTime] as date) as 'Date',
sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountLike' then 1 else 0 end) as 'Likes',
sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountDislike' then 1 else 0 end) as 'Dis likes',
sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountSharing' then 1 else 0 end) as 'Shares',
SUM(case when [dbo].[TelemetryData].[EventName]='DiscountView' then 1 else 0 end) as 'Views',
SUM(case when [dbo].[TelemetryData].[EventName]='DiscountClick' then 1 else 0 end) as 'Clicks',
Sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountCode' then 1 else 0 end) as 'Downloaded codes',
Sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountSave' then 1 else 0 end) as 'Saves',
sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountClickWWW' then 1 else 0 end) as 'Page redirections',
Round(
cast(Sum(case when [dbo].[TelemetryData].[EventName]='DiscountClick' then 1 else 0 end) as float)
/
cast(
case when SUM(case when [dbo].[TelemetryData].[EventName]='DiscountView' then 1 else 0 end) = 0 then 1
else SUM(case when [dbo].[TelemetryData].[EventName]='DiscountView' then 1 else 0 end) end as float)
* 100, 2)
as 'Average CTR',
0 as 'Unique users',
0 as 'New users',
0 as 'Returning users',
Sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountCommentPositive' then 1 else 0 end) as 'Positive comments',
sum(case when [dbo].[TelemetryData].[EventName] = 'DiscountCommentNegative' then 1 else 0 end) as 'Negative comments'
from [dbo].[TelemetryData]
where [dbo].[TelemetryData].[DiscountId] = '5F8851DD-DF77-46DC-885E-46ECA93F021C'
and ([dbo].[TelemetryData].[EventName] = 'DiscountView' or [dbo].[TelemetryData].[EventName] = 'DiscountClick' or
[dbo].[TelemetryData].[EventName] = 'DiscountDislike' or [dbo].[TelemetryData].[EventName] = 'DiscountCode' or
[dbo].[TelemetryData].[EventName] = 'DiscountLike' or [dbo].[TelemetryData].[EventName] = 'DiscountSharing' or
[dbo].[TelemetryData].[EventName] = 'DiscountClickWWW' or [dbo].[TelemetryData].[EventName] = 'DiscountSave' or
[dbo].[TelemetryData].[EventName] = 'DiscountCommentPositive' or [dbo].[TelemetryData].[EventName] = 'DiscountCommentNegative')
group by cast([dbo].[TelemetryData].[EventTime] as date)
order by cast([dbo].[TelemetryData].[EventTime] as date) asc
Now it will be hard...

You want aggregated user information in your results. One obvious and simple solution is to group by date and user first so as to get this information per user and date and only later group by date only.
select
eventdate,
count(*) as unique_users,
count(case when cnt > 1 then 1 end) as returning_users,
count(case when cnt = 1 then 1 end) as new_users
from
(
select cast(eventtime as date) as eventdate, userid, count(*) as cnt
from telemetrydata
where ...
group by cast(eventtime as date), userid
) date_user
group by eventdate;

Could be i don't understand you question but looking to your data seems that you need
select
date
, count(*) as unique
, (count(*) - count(distinct user_id)) as returning
, count(distinct user_id) as new
group by date
were user_id is not null

Try this using a Common Table Expression:
Setup
CREATE TABLE #TelemetryData
(
EventTime Date,
UserId UNIQUEIDENTIFIER NULL
)
INSERT INTO #TelemetryData
VALUES
('2016-11-09', '0536B088-D3DE-4C0E-903F-C2463D0AAB7E'),
('2016-11-09', '866D70EC-93FD-4C30-BC54-C7B954F255BE'),
('2016-11-09', '6C090D6B-9842-4CB0-9E10-F9B941C8D3A1'),
('2016-11-09', 'FB1DD63E-F098-4191-B8F4-BEA4F9776B54'),
('2016-11-09', 'FB1DD63E-F098-4191-B8F4-BEA4F9776B54'),
('2016-11-10', '0536B088-D3DE-4C0E-903F-C2463D0AAB7E'),
('2016-11-10', NULL),
('2016-11-10', '0536B088-D3DE-4C0E-903F-C2463D0AAB7E'),
('2016-11-11', '0536B088-D3DE-4C0E-903F-C2463D0AAB7E'),
('2016-11-11', '0536B088-D3DE-4C0E-903F-C2463D0AAB7E')
Query
;WITH CTE
AS
(
SELECT EventTime,
UserId,
COUNT(*) cnt,
ROW_NUMBER() OVER (PARTITION BY EventTime ORDER BY EventTime) RN
FROM #TelemetryData
GROUP BY EventTime, UserId
)
SELECT EventTime,
MAX(RN) AS [Unique],
SUM(CASE WHEN cnt > 1 THEN 1 ELSE 0 END) as New,
SUM(CASE WHEN cnt = 1 THEN 1 ELSE 0 END) AS Returning
FROM CTE
GROUP BY EventTime
Results
EventTime Unique New Returning
2016-11-09 4 1 3
2016-11-10 2 1 1
2016-11-11 1 1 0

Try below query
select Date, uniques, returning, uniques-returning as new
from (
select Date,
sum(case when row_num = 1 then 1 else 0 end) uniques,
sum(case when row_num = 2 then 1 else 0 end) returning
from(
select cast(EventTime as date) as Date,
ROW_NUMBER() over(partition by EventTime, userid order by EventTime) row_num
from TelemetryData) cte1
group by Date)cte2
Hope this should help you

The following query should work:
select EventTime,
max(DistinctRank) [Unique],
sum(CountOfDistinct - 1) Returning,
max(DistinctRank) - sum(CountOfDistinct - 1) New
from
(select distinct EventTime,
UserId,
rank() over (partition by EventTime order by UserId) DistinctRank,
count(1) over (partition by EventTime, UserId) CountOfDistinct
from TelemetryData) sub
group by EventTime
The subquery (run it separately and see for yourself) will return the unique combinations of EventTime and UserID, along with the the rank of each unique UserId for a given date, and the count of distinct values for each combination of EventTime and UserId:
EventDate UserId DistinctRank CountOfDistinct
2016-11-09 00:00:00.000 0536B088-D3DE-4C0E-903F-C2463D0AAB7E 1 1
2016-11-09 00:00:00.000 6C090D6B-9842-4CB0-9E10-F9B941C8D3A1 2 1
2016-11-09 00:00:00.000 866D70EC-93FD-4C30-BC54-C7B954F255BE 3 1
2016-11-09 00:00:00.000 FB1DD63E-F098-4191-B8F4-BEA4F9776B54 4 2
2016-11-10 00:00:00.000 NULL 1 1
2016-11-10 00:00:00.000 0536B088-D3DE-4C0E-903F-C2463D0AAB7E 2 2
2016-11-11 00:00:00.000 0536B088-D3DE-4C0E-903F-C2463D0AAB7E 1 2
Then the outer query gets the maximum DistinctRank for each unique pair, which is the number of unique UserIds for the EventDate, and essentially the sum of the subquery records where there were duplicates in UserId for a given EventDate, which is the number of returning users. The New column is just the difference between Unique and Returning. The result is:
Event Date Unique Returning New
2016-11-09 00:00:00.000 4 1 3
2016-11-10 00:00:00.000 2 1 1
2016-11-11 00:00:00.000 1 1 0

Related

How to count records by store, day wise and in 2 hours range period with pivot table format?

I have multiple stores records with user's punch records.
I would like to create a report for each store' day-wise which 2 hours have how many employees was working?
Clock In ID Last Name First Name In time Out time
912 Bedolla Jorge 1/1/2021 7:29 1/1/2021 11:31
912 Romero Gabriel 1/1/2021 10:55 1/1/2021 14:07
912 Bedolla Jorge 1/1/2021 12:00 1/1/2021 16:07
912 Zaragoza Daniel 1/1/2021 13:06 1/1/2021 14:57
912 Thaxton Christopher 1/1/2021 14:01 1/1/2021 16:57
912 Jones Elena 1/1/2021 14:01 1/1/2021 16:35
912 Zaragoza Daniel 1/1/2021 15:12 1/1/2021 17:09
912 Jones Elena 1/1/2021 16:45 1/1/2021 18:05
912 Smith Kirsten 1/1/2021 17:30 1/1/2021 20:01
912 Zaragoza Daniel 1/1/2021 17:41 1/1/2021 21:49
Looking for a result something like below. (below result data is incorrect)
store ForDate 0-2 2-4 4-6 6-8 8-10 10-12 12-14 14-16 16-18 18-20 20-22 22-0
912 2021-01-01 0 0 0 1 0 1 2 3 3 2 3 0
912 2021-01-02 0 0 2 1 2 3 2 4 2 3 3 0
912 2021-01-03 0 0 1 1 2 2 2 2 3 0 2 0
912 2021-01-04 0 0 2 0 2 1 2 2 3 3 1 0
912 2021-01-05 0 0 2 1 1 3 4 4 2 2 1 0
912 2021-01-06 0 0 2 0 2 1 2 3 3 2 3 0
912 2021-01-07 0 0 2 1 2 1 3 4 2 2 0 0
912 2021-01-08 0 0 2 2 2 1 3 2 1 2 1 0
912 2021-01-09 0 0 1 1 0 3 1 3 2 2 3 0
912 2021-01-10 0 0 2 2 1 2 2 1 1 2 2 0
I tried to solve with below query but it's wrong and stil it's just inTime but outTime is pending.
SELECT TOP 10 store, ForDate,
ISNULL([0], 0) + ISNULL([1], 0) AS [0-1],
ISNULL([2], 0) + ISNULL([3], 0) AS [2-3],
ISNULL([4], 0) + ISNULL([5], 0) AS [4-5],
ISNULL([6], 0) + ISNULL([7], 0) AS [6-7],
ISNULL([8], 0) + ISNULL([9], 0) AS [8-9],
ISNULL([10], 0) + ISNULL([11], 0) AS [10-11],
ISNULL([12], 0) + ISNULL([13], 0) AS [12-13],
ISNULL([14], 0) + ISNULL([15], 0) AS [14-15],
ISNULL([16], 0) + ISNULL([17], 0) AS [16-17],
ISNULL([18], 0) + ISNULL([19], 0) AS [18-19],
ISNULL([20], 0) + ISNULL([21], 0) AS [20-21],
ISNULL([22], 0) + ISNULL([23], 0) AS [22-23]
FROM (
select *
from
(
select store, CAST(InTime as date) AS ForDate, DATEPART(hour,InTime) AS OnHour, COUNT(*) AS Totals
from Punches
GROUP BY store, CAST(InTime as date),
DATEPART(hour,InTime)
) src
pivot
(
sum(Totals)
for OnHour in ([0],[1], [2], [3],[4], [5], [6],[7],[8], [9], [10],[11], [12], [13],[14], [15], [16],[17],[18], [19],[20],[21], [22], [23])
) piv
) t1
order by store, ForDate
Here is SQL Fiddle with data.
https://www.db-fiddle.com/f/jo4atDmmj8cshyK1CWWo7x/2
That is insane but worth trying
SELECT storeid, ForDate,
ISNULL([0], 0) + ISNULL([1], 0) AS [0-1],
ISNULL([2], 0) + ISNULL([3], 0) AS [2-3],
ISNULL([4], 0) + ISNULL([5], 0) AS [4-5],
ISNULL([6], 0) + ISNULL([7], 0) AS [6-7],
ISNULL([8], 0) + ISNULL([9], 0) AS [8-9],
ISNULL([10], 0) + ISNULL([11], 0) AS [10-11],
ISNULL([12], 0) + ISNULL([13], 0) AS [12-13],
ISNULL([14], 0) + ISNULL([15], 0) AS [14-15],
ISNULL([16], 0) + ISNULL([17], 0) AS [16-17],
ISNULL([18], 0) + ISNULL([19], 0) AS [18-19],
ISNULL([20], 0) + ISNULL([21], 0) AS [20-21],
ISNULL([22], 0) + ISNULL([23], 0) AS [22-23]
FROM (
select *
from
(
SELECT [Dates].StoreId, [Dates].ForDate, Hours.hour OnHour, COUNT(*) Totals FROM (
SELECT storeId, CAST(InTime as date) AS ForDate FROM Punches
UNION
SELECT storeId, CAST(OutTime AS date) AS ForDate FROM Punches
) [Dates] JOIN (
SELECT * FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23)) hours([hour])
) [Hours] ON 1=1
JOIN
(
SELECT * FROM dbo.Punches
) p
ON p.StoreId = [Dates].StoreId
AND (DATEADD(HOUR, [Hours].[hour], CAST([Dates].ForDate AS DATETIME)) BETWEEN CAST(p.InTime AS DATETIME) AND CAST(p.Outtime AS DATETIME))
GROUP BY [Dates].StoreId, Dates.ForDate, [hour]
) src
pivot
(
sum(Totals)
for OnHour in ([0],[1], [2], [3],[4], [5], [6],[7],[8], [9], [10],[11], [12], [13],[14], [15], [16],[17],[18], [19],[20],[21], [22], [23])
) piv
) t1
order by storeid, ForDate
Let's go a bit deeper:
I generated all possible dates by this part:
SELECT storeId, CAST(InTime as date) AS ForDate FROM Punches
UNION
SELECT storeId, CAST(OutTime AS date) AS ForDate FROM Punches
And all possible hours by doing this:
SELECT * FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23)) hours([hour])
Then I joined them to find all possible date-hours.
After that, I just joined them with punches and counted the punch if the generated date-hour is between inTime and OutTime by adding this condition:
(DATEADD(HOUR, [Hours].[hour], CAST([Dates].ForDate AS DATETIME)) BETWEEN CAST(p.InTime AS DATETIME) AND CAST(p.Outtime AS DATETIME))
The rest is exactly the same as your code
You can use simple CASE statement to get what you so far try-
SELECT StoreId, CAST(InTime as Date) as ForDate,
SUM(CASE WHEN DATEPART(hour,InTime) in (0,1) THEN 1 ELSE 0 END) AS [0-1],
SUM(CASE WHEN DATEPART(hour,InTime) in (2,3) THEN 1 ELSE 0 END) AS [2-3],
SUM(CASE WHEN DATEPART(hour,InTime) in (4,5) THEN 1 ELSE 0 END) AS [4-5],
SUM(CASE WHEN DATEPART(hour,InTime) in (6,7) THEN 1 ELSE 0 END) AS [6-7],
SUM(CASE WHEN DATEPART(hour,InTime) in (8,9) THEN 1 ELSE 0 END) AS [8-9],
SUM(CASE WHEN DATEPART(hour,InTime) in (10,11) THEN 1 ELSE 0 END) AS [10-11],
SUM(CASE WHEN DATEPART(hour,InTime) in (12,13) THEN 1 ELSE 0 END) AS [12-13],
SUM(CASE WHEN DATEPART(hour,InTime) in (14,15) THEN 1 ELSE 0 END) AS [14-15],
SUM(CASE WHEN DATEPART(hour,InTime) in (16,17) THEN 1 ELSE 0 END) AS [16-17],
SUM(CASE WHEN DATEPART(hour,InTime) in (18,19) THEN 1 ELSE 0 END) AS [18-19],
SUM(CASE WHEN DATEPART(hour,InTime) in (20,21) THEN 1 ELSE 0 END) AS [20-21],
SUM(CASE WHEN DATEPART(hour,InTime) in (22,23) THEN 1 ELSE 0 END) AS [22-23]
FROM Punches
GROUP BY StoreId, CAST(InTime as Date)
And for your final result use below query:-
Select StoreId,ForDate,
SUM(CASE WHEN [0-2]>0 THEN 1 ELSE 0 END) AS [0-2],
SUM(CASE WHEN [2-4]>0 THEN 1 ELSE 0 END) AS [2-4],
SUM(CASE WHEN [4-6]>0 THEN 1 ELSE 0 END) AS [4-6],
SUM(CASE WHEN [6-8]>0 THEN 1 ELSE 0 END) AS [6-8],
SUM(CASE WHEN [8-10]>0 THEN 1 ELSE 0 END) AS [8-10],
SUM(CASE WHEN [10-12]>0 THEN 1 ELSE 0 END) AS [10-12],
SUM(CASE WHEN [12-14]>0 THEN 1 ELSE 0 END) AS [12-14],
SUM(CASE WHEN [14-16]>0 THEN 1 ELSE 0 END) AS [14-16],
SUM(CASE WHEN [16-18]>0 THEN 1 ELSE 0 END) AS [16-18],
SUM(CASE WHEN [18-20]>0 THEN 1 ELSE 0 END) AS [18-20],
SUM(CASE WHEN [20-22]>0 THEN 1 ELSE 0 END) AS [20-22],
SUM(CASE WHEN [22-24]>0 THEN 1 ELSE 0 END) AS [22-24]
from
(SELECT StoreId,FirstName+LastName as Name, CAST(InTime as Date) as ForDate,
SUM(CASE WHEN DATEPART(hour,InTime) in (0,1) OR (DATEPART(hour,InTime)<0 AND DATEPART(hour,OutTime)>=1) THEN 1 ELSE 0 END) AS [0-2],
SUM(CASE WHEN DATEPART(hour,InTime) in (2,3) OR (DATEPART(hour,InTime)<2 AND DATEPART(hour,OutTime)>=2) THEN 1 ELSE 0 END) AS [2-4],
SUM(CASE WHEN DATEPART(hour,InTime) in (4,5) OR (DATEPART(hour,InTime)<4 AND DATEPART(hour,OutTime)>=4) THEN 1 ELSE 0 END) AS [4-6],
SUM(CASE WHEN DATEPART(hour,InTime) in (6,7) OR (DATEPART(hour,InTime)<6 AND DATEPART(hour,OutTime)>=6) THEN 1 ELSE 0 END) AS [6-8],
SUM(CASE WHEN DATEPART(hour,InTime) in (8,9) OR (DATEPART(hour,InTime)<8 AND DATEPART(hour,OutTime)>=8) THEN 1 ELSE 0 END) AS [8-10],
SUM(CASE WHEN DATEPART(hour,InTime) in (10,11) OR (DATEPART(hour,InTime)<10 AND DATEPART(hour,OutTime)>=10) THEN 1 ELSE 0 END) AS [10-12],
SUM(CASE WHEN DATEPART(hour,InTime) in (12,13) OR (DATEPART(hour,InTime)<12 AND DATEPART(hour,OutTime)>=12) THEN 1 ELSE 0 END) AS [12-14],
SUM(CASE WHEN DATEPART(hour,InTime) in (14,15) OR (DATEPART(hour,InTime)<14 AND DATEPART(hour,OutTime)>=14) THEN 1 ELSE 0 END) AS [14-16],
SUM(CASE WHEN DATEPART(hour,InTime) in (16,17) OR (DATEPART(hour,InTime)<16 AND DATEPART(hour,OutTime)>=16) THEN 1 ELSE 0 END) AS [16-18],
SUM(CASE WHEN DATEPART(hour,InTime) in (18,19) OR (DATEPART(hour,InTime)<18 AND DATEPART(hour,OutTime)>=18) THEN 1 ELSE 0 END) AS [18-20],
SUM(CASE WHEN DATEPART(hour,InTime) in (20,21) OR (DATEPART(hour,InTime)<20 AND DATEPART(hour,OutTime)>=20) THEN 1 ELSE 0 END) AS [20-22],
SUM(CASE WHEN DATEPART(hour,InTime) in (22,23) OR (DATEPART(hour,InTime)<22 AND DATEPART(hour,OutTime)>=22) THEN 1 ELSE 0 END) AS [22-24]
FROM Punches
GROUP BY StoreId,FirstName+LastName,CAST(InTime as Date)) detailsQuery
GROUP BY StoreId,ForDate

Group by datepart and find total count of individual values of each record

This is table structure;
ID Score Valid CreatedDate
1 A 1 2018-02-19 23:33:10.297
2 C 0 2018-02-19 23:32:40.700
3 B 1 2018-02-19 23:32:30.247
4 A 1 2018-02-19 23:31:37.153
5 B 0 2018-02-19 23:25:08.667
...
I need to find total number of each score and valid in each month
I mean final result should be like
Month A B C D E Valid(1) NotValid(0)
January 123 343 1021 98 12 1287 480
February 516 421 321 441 421 987 672
...
This is what I tried;
SELECT DATEPART(year, CreatedDate) as Ay,
(select count(*) from TableResults where Score='A') as 'A',
(select count(*) from TableResults where Score='B') as 'B',
...
FROM TableResults
group by DATEPART(MONTH, CreatedDate)
but couldn't figure how to calculate all occurrence of scores on each month.
Use conditional aggregation.
SELECT DATEPART(year, CreatedDate) as YR
, DATEPART(month, CreatedDate) MO
, sum(Case when score = 'A' then 1 else 0 end) as A
, sum(Case when score = 'B' then 1 else 0 end) as B
, sum(Case when score = 'C' then 1 else 0 end) as C
, sum(Case when score = 'D' then 1 else 0 end) as D
, sum(Case when score = 'E' then 1 else 0 end) as E
, sum(case when valid = 1 then 1 else 0 end) as Valid
, sum(case when valid = 0 then 1 else 0 end) as NotValid
FROM TableResults
GROUP BY DATEPART(MONTH, CreatedDate), DATEPART(year, CreatedDate)
I'm not a big fan of queries in the select; I find they tend to cause performance problems in the long run. Since we're aggregating here I just applied the conditional logic to all the columns.

Cohort Analysis in SQL while recounting users

I'm trying to create a cohort query using SQL.
Usually with cohort analysis we look at users and check if a user who performed a specific action at a specific time and count if that user performs the same action over time.
WITH by_week
AS (SELECT
user_id,
TD_DATE_TRUNC('week', login_time) AS login_week
FROM logins
GROUP BY 1, 2),
with_first_week
AS (SELECT
user_id,
login_week,
FIRST_VALUE(login_week) OVER (PARTITION BY user_id ORDER BY login_week) AS first_week
FROM by_week),
with_week_number
AS (SELECT
user_id,
login_week,
first_week,
(login_week - first_week) / (24 * 60 * 60 * 7) AS week_number
FROM with_first_week)
SELECT
TD_TIME_FORMAT(first_week, 'yyyy-MM-dd') AS first_week,
SUM(CASE WHEN week_number = 1 THEN 1 ELSE 0 END) AS week_1,
SUM(CASE WHEN week_number = 2 THEN 1 ELSE 0 END) AS week_2,
SUM(CASE WHEN week_number = 3 THEN 1 ELSE 0 END) AS week_3,
SUM(CASE WHEN week_number = 4 THEN 1 ELSE 0 END) AS week_4,
SUM(CASE WHEN week_number = 5 THEN 1 ELSE 0 END) AS week_5,
SUM(CASE WHEN week_number = 6 THEN 1 ELSE 0 END) AS week_6,
SUM(CASE WHEN week_number = 7 THEN 1 ELSE 0 END) AS week_7,
SUM(CASE WHEN week_number = 8 THEN 1 ELSE 0 END) AS week_8,
SUM(CASE WHEN week_number = 9 THEN 1 ELSE 0 END) AS week_9
FROM with_week_number
GROUP BY 1
ORDER BY 1
But let say now I don't care that much about first time/user-level analysis and I only want to see if my login action increases over time (i.e I want to add up logins of the first cohort during week 2 with logins of the second cohort in week 1). Is there a simple/elegant way to do this?
Edit:
Giving an example below
WeekStart Week1 Week2 Week 3
2017/05/03 66 **53** **49**
2017/05/10 (**53**+74) (**49**+70) **65**
2017/05/17 (**49**+ 70 + 45) (**65** + 80) etc.
I think you need to group by login_week instead of first_week so you count all logins during the given week in every row, not by cohort, and then you have to use >= instead of = so it will sum up this week's cohort with all older cohorts in any given row.
WITH
by_week AS (
SELECT
user_id,
TD_DATE_TRUNC('week', login_time) AS login_week
FROM logins
GROUP BY 1, 2
)
,with_first_week AS (
SELECT
user_id,
login_week,
FIRST_VALUE(login_week) OVER (PARTITION BY user_id ORDER BY login_week) AS first_week
FROM by_week
)
,with_week_number AS (
SELECT
user_id,
login_week,
first_week,
(login_week - first_week) / (24 * 60 * 60 * 7) AS week_number
FROM with_first_week
)
SELECT
TD_TIME_FORMAT(login_week, 'yyyy-MM-dd') AS login_week,
SUM(CASE WHEN week_number>= 1 THEN 1 ELSE 0 END) AS week_1,
SUM(CASE WHEN week_number>= 2 THEN 1 ELSE 0 END) AS week_2,
SUM(CASE WHEN week_number>= 3 THEN 1 ELSE 0 END) AS week_3,
SUM(CASE WHEN week_number>= 4 THEN 1 ELSE 0 END) AS week_4,
SUM(CASE WHEN week_number>= 5 THEN 1 ELSE 0 END) AS week_5,
SUM(CASE WHEN week_number>= 6 THEN 1 ELSE 0 END) AS week_6,
SUM(CASE WHEN week_number>= 7 THEN 1 ELSE 0 END) AS week_7,
SUM(CASE WHEN week_number>= 8 THEN 1 ELSE 0 END) AS week_8,
SUM(CASE WHEN week_number>= 9 THEN 1 ELSE 0 END) AS week_9
FROM with_week_number
GROUP BY 1
ORDER BY 1;

How to count sql from one column, and display it in two column

I have a table like this:
idrecord | date
----------------------------------------------
INC-20140308102029 | 2014-03-08 00:00:00.000
INC-20140308102840 | 2014-03-06 00:00:00.000
INC-20140310164404 | 2014-03-10 00:00:00.000
INC-20140311075714 | 2014-03-09 00:00:00.000
NRM-20140310130512 | 2014-04-02 00:00:00.000
NRM-20140311134720 | 2014-03-11 00:00:00.000
USF-20140317212232 | 2014-03-17 00:00:00.000
USF-20140321075402 | 2014-03-18 00:00:00.000
USF-20140321083137 | 2014-03-21 00:00:00.000
how to count this table and display result like this:
month | INC | NRM | USF
march | 4 | 1 | 3
April | 0 | 1 | 0
Thank you
You'd use case to count 1 or zero depending on the string matching or not. Use sum to count.
select
extract(month from thedate) as whichmonth,
sum( case when idrecord like 'INC%' then 1 else 0 end) as inc,
sum( case when idrecord like 'NRM%' then 1 else 0 end) as nrm,
sum( case when idrecord like 'USF%' then 1 else 0 end) as usf
from mytable
group by extract(month from thedate);
The function to extract the month from the date may vary from dbms to dbms. Look the appropriate function up in Google, if extract doesn't work for you.
Don't use the name date for a column. Date is a reserved word in SQL.
Try this
SELECT convert(char(3), date, 0) AS Month,
SUM(Case when LEFT(idrecord,3) = 'INC' then 1 else 0 end) as 'INC',
SUM(Case when LEFT(idrecord,3) = 'NRM' then 1 else 0 end) as 'NRM',
SUM(Case when LEFT(idrecord,3) = 'USF' then 1 else 0 end) as 'USF'
FROM Table1
Group By convert(char(3), date, 0)
Fiddle Demo
or:
SELECT datename(mm, date) AS Month,
SUM(Case when LEFT(idrecord,3) = 'INC' then 1 else 0 end) as 'INC',
SUM(Case when LEFT(idrecord,3) = 'NRM' then 1 else 0 end) as 'NRM',
SUM(Case when LEFT(idrecord,3) = 'USF' then 1 else 0 end) as 'USF'
FROM Table1
Group By datename(mm, date)
Fiddle Demo
Output:
month | INC | NRM | USF
march | 4 | 1 | 3
April | 0 | 1 | 0
try this one
select month (date) as month,
count( case when idrecord like 'INC%' then 1 else 0 end) as inc,
count( case when idrecord like 'NRM%' then 1 else 0 end) as nrm,
count( case when idrecord like 'USF%' then 1 else 0 end) as usf
from table
group by month;

select multiple sum how to filter by date correctly

Here is what I have currently that does not filter anything by createdDate.
SELECT [employeeID]
,employeeName
,isnull((SELECT SUM(case when clientID != 10 then timeSpent else 0 end)),0) as 'billable'
,isnull((SELECT SUM(case when clientID = 10 then timeSpent else 0 end)),0) as 'nonBillable'
FROM [myDB].[dbo].[myTable]
group by employeeID,employeeName
which outputs:
employeeID employeeName billable nonbillable
---------- ------------ -------- -----------
1 tom 5230 2302
2 dick 25 8439
3 harry 2430 9433
accurate output would be similar but with sum of values only within the date range:
employeeID employeeName billable nonbillable
---------- ------------ -------- -----------
1 tom 35 5
2 dick 25 15
3 harry 2 48
[myTable] has the following fields: employeeID,employeeName,clientID,timeSpent,createdDate
I need to be able to add a filter in to each of the select sum statements similar to the following: WHERE createdDate BETWEEN ('2012-10-01') AND ('2012-10-07')
The following variations all fail either with SQL Errors or inaccurate output:
SELECT [employeeID]
,employeeName
,isnull((SELECT SUM(case when clientID != 10 then timeSpent else 0 end)),0) as 'billable'
,isnull((SELECT SUM(case when clientID = 10 then timeSpent else 0 end)),0) as 'nonBillable'
FROM [myDB].[dbo].[myTable]
WHERE createdDate BETWEEN ('2012-10-01') AND ('2012-10-07')
group by employeeID,employeeName
SELECT DISTINCT [employeeID]
,employeeName
,isnull((SELECT SUM(case when clientID != 10 then timeSpent else 0 end)),0) as 'billable'
,isnull((SELECT SUM(case when clientID = 10 then timeSpent else 0 end)),0) as 'nonBillable'
FROM [myDB].[dbo].[myTable]
WHERE createdDate BETWEEN ('2012-10-01') AND ('2012-10-07')
group by employeeID,employeeName
SELECT [employeeID]
,employeeName
,isnull((SELECT SUM(case when clientID != 10 then timeSpent else 0 end)WHERE createdDate BETWEEN ('2012-10-01') AND ('2012-10-07')),0) as 'billable'
,isnull((SELECT SUM(case when clientID = 10 then timeSpent else 0 end)WHERE createdDate BETWEEN ('2012-10-01') AND ('2012-10-07')),0) as 'nonBillable'
FROM [myDB].[dbo].[myTable]
group by employeeID,employeeName,createdDate
Any help would be greatly appreciated.
Thanks in advance.
The first query should give you the correct results
SELECT [employeeID]
,employeeName
,isnull((SELECT SUM(case when clientID != 10 then timeSpent else 0 end)),0) as 'billable'
,isnull((SELECT SUM(case when clientID = 10 then timeSpent else 0 end)),0) as 'nonBillable'
FROM [myDB].[dbo].[myTable]
WHERE createdDate BETWEEN '2012-10-01' AND '2012-10-07'
group by employeeID,employeeName
However, if createdDate is a datetime type, then it will only return values between '2012-01-01 00:00' and '2012-10-07 00:00' - nothing after 2012-10-07 00:01. Ideally you would specify the filter dates as dates, rather than strings.