SQL count per day and add together all following days - sql

I'm trying to write a SQL query to count users per day and add the result together. I'm stuck because I don't know how to dynamically add the results together.
Table:
UserId | CreateDate
-------+----------------------------
1 | 2016-06-23 13:59:24.0000000
2 | 2016-06-23 15:59:24.0000000
3 | 2016-06-24 05:59:24.0000000
...
I have following query to count the registrations per day.
SELECT
CONVERT(date, u.CreateDate) as [Date], Count(UserId) as [Count]
FROM
User as u
GROUP BY
CONVERT(date, u.CreateDate)
ORDER BY
[Date]
I have no idea how to add up the results. I hope that SQL Server 2008 R2 has a built-in function for my case. Or do I need to create temp tables?
Assuming Day 1 has 2 registrations and Day 2 has 1 registration and Day 3 has 4 registrations, I would like to receive a result like this:
2016-06-23 | 2
2016-06-24 | 2 + 1 = 3
2016-06-25 | 3 + 4 = 7
I would need a dynamic solution because the query will have another restriction by date => Where CreateDate bewteen x and y.
Thanks
Ruedi

You can use sum window function to get the running total.
select [Date],sum([Count]) over(order by [Date])
from (SELECT CONVERT(date, u.CreateDate) as [Date], Count(UserId) as [Count]
FROM User as u
GROUP BY CONVERT(date, u.CreateDate)
) x
order by 1
Add a where clause to filter for a specific date range in the inner query.

with redshift database
select [Date],sum([Count]) over(order by [Date] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
from (SELECT CONVERT(date, u.CreateDate) as [Date], Count(UserId) as [Count]
FROM User as u
GROUP BY CONVERT(date, u.CreateDate)
) x
order by 1

Related

SQL Server : count types with totals by date change

I need to count a value (M_Id) at each change of a date (RS_Date) and create a column grouped by the RS_Date that has an active total from that date.
So the table is:
Ep_Id Oa_Id M_Id M_StartDate RS_Date
--------------------------------------------
1 2001 5 1/1/2014 1/1/2014
1 2001 9 1/1/2014 1/1/2014
1 2001 3 1/1/2014 1/1/2014
1 2001 11 1/1/2014 1/1/2014
1 2001 2 1/1/2014 1/1/2014
1 2067 7 1/1/2014 1/5/2014
1 2067 1 1/1/2014 1/5/2014
1 3099 12 1/1/2014 3/2/2014
1 3099 14 2/14/2014 3/2/2014
1 3099 4 2/14/2014 3/2/2014
So my goal is like
RS_Date Active
-----------------
1/1/2014 5
1/5/2014 7
3/2/2014 10
If the M_startDate = RS_Date I need to count the M_id and then for
each RS_Date that is not equal to the start date I need to count the M_Id and then add that to the M_StartDate count and then count the next RS_Date and add that to the last active count.
I can get the basic counts with something like
(Case when M_StartDate <= RS_Date
then [m_Id] end) as Test.
But I am stuck as how to get to the result I want.
Any help would be greatly appreciated.
Brian
-added in response to comments
I am using Server Ver 10
If using SQL SERVER 2012+ you can use ROWS with your the analytic/window functions:
;with cte AS (SELECT RS_Date
,COUNT(DISTINCT M_ID) AS CT
FROM Table1
GROUP BY RS_Date
)
SELECT *,SUM(CT) OVER(ORDER BY RS_Date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Run_CT
FROM cte
Demo: SQL Fiddle
If stuck using something prior to 2012 you can use:
;with cte AS (SELECT RS_Date
,COUNT(DISTINCT M_ID) AS CT
FROM Table1
GROUP BY RS_Date
)
SELECT a.RS_Date
,SUM(b.CT)
FROM cte a
LEFT JOIN cte b
ON a.RS_DAte >= b.RS_Date
GROUP BY a.RS_Date
Demo: SQL Fiddle
You need a cumulative sum, easy in SQL Server 2012 using Windowed Aggregate Functions. Based on your description this will return the expected result
SELECT p_id, RS_Date,
SUM(COUNT(*))
OVER (PARTITION BY p_id
ORDER BY RS_Date
ROWS UNBOUNDED PRECEDING)
FROM tab
GROUP BY p_id, RS_Date
It looks like you want something like this:
SELECT
RS_Date,
SUM(c) OVER (PARTITION BY M_StartDate ORDER BY RS_Date ROWS UNBOUNDED PRECEEDING)
FROM
(
SELECT M_StartDate, RS_Date, COUNT(DISTINCT M_Id) AS c
FROM my_table
GROUP BY M_StartDate, RS_Date
) counts
The inline view computes the counts of distinct M_Id values within each (M_StartDate, RS_Date) group (distinctness enforced only within the group), and the outer query uses the analytic version of SUM() to add up the counts within each M_StartDate.
Note that this particular query will not exactly reproduce your example results. It will instead produce:
RS_Date Active
-----------------
1/1/2014 5
1/5/2014 7
3/2/2014 8
3/2/2014 2
This is on account of some rows in your example data with RS_Date 3/2/2014 having a later M_StartDate than others. If this is not what you want then you need to clarify the question, which currently seems a bit inconsistent.
Unfortunately, analytic functions are not available until SQL Server 2012. In SQL Server 2010, the job is messier. It could be done like this:
WITH gc AS (
SELECT M_StartDate, RS_Date, COUNT(DISTINCT M_Id) AS c
FROM my_table
GROUP BY M_StartDate, RS_Date
)
SELECT
RS_Date,
(
SELECT SUM(c)
FROM gc2
WHERE gc2.M_StartDate = gc.M_StartDate AND gc2.RS_Date <= gc.RS_Date
) AS Active
FROM gc
If you are using SQL 2012 or newer you can use LAG to produce a running total.
https://msdn.microsoft.com/en-us/library/hh231256(v=sql.110).aspx

Open Ticket Count Per Day

I have a table that looks like this
id | Submit_Date | Close_Date
------------------------------
1 | 2015-02-01 | 2015-02-05
2 | 2015-02-02 | 2015-02-04
3 | 2015-02-03 | 2015-02-05
4 | 2015-02-04 | 2015-02-06
5 | 2015-02-05 | 2015-02-07
6 | 2015-02-06 | 2015-02-07
7 | 2015-02-07 | 2015-02-08
I can get a count of how many ticket were open on a particular day with this:
Select count(*) from tickets where '2015-02-05' BETWEEN Submit_Date and Close_Date
This gives me 4, but I need this count for each day of a month. I don't want to have to write 30 queries to handle this. Is there a way to capture broken down by multiple days?
I created a solution a way back using a mix of #Heinzi s solution with the trick from Generate a resultset of incrementing dates in TSQL
declare #dt datetime, #dtEnd datetime
set #dt = getdate()
set #dtEnd = dateadd(day, 100, #dt)
SELECT dates.myDate,
(SELECT COUNT(*)
FROM tickets
WHERE myDate BETWEEN Submit_Date and Close_Date
)
FROM
(select Dates_To_Checkselect dateadd(day, number, #dt) mydate
from
(select distinct number from master.dbo.spt_values
where name is null
) n
where dateadd(day, number, #dt) < #dtEnd) dates
Code is combined from memory, I don't have it in front of me so there can be some typo's
First, you'll need a table that contains each date you want to check. You can use a temporary table for that. Let's assume that this table is called Dates_To_Check and has a field myDate:
SELECT myDate,
(SELECT COUNT(*)
FROM tickets
WHERE myDate BETWEEN Submit_Date and Close_Date)
FROM Dates_To_Check
Alternatively, you can create a huge table containing every possible date and use a WHERE clause to restrict the dates to those you are interested in.
If you're in SQL Server 2012 or newer you can do this using window functions with a small trick where you add 1 to the open days -1 to the closing days and then do a running total of this amount:
select distinct date, sum(opencnt) over (order by date) from (
select
Submit_Date as date,
1 as opencnt
from
ticket
union all
select
dateadd(day, 1, Close_Date),
-1
from
ticket
) TMP
There's a dateadd + 1 day to include the close date amount to that day
You could generate the list of dates and then retrieve the count for each date in your dateset.
The cte part generates the date list since the beginning of the year (an ssumption) and the next part calculates the count from your data set.
with cte as
(select cast('2015-01-01' as date) dt // you should change this part to the correct start date
union all
select dateadd(DD,1,dt) dt from cte
where dt<getdate()
)
select count(*)
from tickets
inner join cte
on cte.dt between Submit_Date and Close_Date
group by cte.dt

SQL Server - Get count for each pharmacy's outbound usage for each month

I am trying to write a query to select the total outbound usage of each pharmacy in my database table for each month.
Here is what I have so far, it outputs the correct data. But I want to eliminate the amount of rows selected
select pharmacyid, count(*) as usage, month(datecalled) as month
from outboundcalldata
where datepart(year, datecalled) = 2014
group by pharmacyid, YEAR(DateCalled), month(datecalled)
order by pharmacyid, month
example of output:
pharmacyid|usage| month
-----------------------
2220000006| 10 | 2
2220000006| 11 | 3
2220000006| 900 | 4
2220000006| 30 | 5
2220000007| 34 | 2
2220000007| 300 | 3
2220000007| 145 | 4
Instead I would like it to output 1 row per pharmacy and a column for each month.
;WITH CTE AS
(
select pharmacyid, count(*) as usage, month(datecalled) as [month]
from outboundcalldata
where datepart(year, datecalled) = 2014
group by pharmacyid, YEAR(DateCalled), month(datecalled)
)
SELECT *
FROM CTE C
PIVOT (SUM(usage)
FOR [month]
IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
)p

SQL join two record into one row with multiple column

i want to join two record (from same table) into one row with multiple column.
employment history structure as follows:
StaffID StartDate EndDate DeptID
==================================================
1 2010-10-01 2011-01-19 1
1 2011-01-20 2012-12-31 2
1 2013-01-01 2013-05-29 4
how can i join the two rows into one row if same StaffID and the 2nd record startdate is 1 day after the enddate of 1st record (continuous employment)
the output should like this
StaffID EffectiveDate New_DeptID Prev_DeptID
==================================================
1 2011-01-20 2 1
1 2013-01-01 4 2
the following is my sql statement but it doesn't work
select distinct
ca1.StaffID,
ca1.ProjectDepartment as Prev_DeptID, ca1.StartDate, ca1.EndDate,
ca2.ProjectDepartment as New_DeptID, ca2.StartDate, ca2.EndDate
from
emp_hist as ca1,
emp_hist as ca2
where
(ca1.StaffID = ca2.StaffID)
and ca1.StartDate<>ca2.StartDate
and ca1.EndDate <>ca2.EndDate
and ca2.startdate= DATEADD(day, 1, ca1.enddate)
for example,
two records (true data) in the table:
StaffID StartDate EndDate DeptID
===========================================================================
1 2010-04-12 12:00:00.000 2013-02-28 00:00:00.000 1
1 2013-03-01 12:00:00.000 2013-08-29 11:02:59.877 2
i cannot retrieve this record by using my sql statement
Your problem is that the dates have a time component. You appear to be using SQL Server. You can fix your query by doing this:
select ca1.StaffID,
ca1.ProjectDepartment as Prev_DeptID, ca1.StartDate, ca1.EndDate,
ca2.ProjectDepartment as New_DeptID, ca2.StartDate, ca2.EndDate
from emp_hist as ca1 join
emp_hist as ca2
on ca1.StaffID = ca2.StaffID and
cast(ca1.StartDate as date) <> cast(ca2.StartDate as date) and
cast(ca1.EndDate as date) <> cast(ca2.EndDate as date) and
cast(ca2.startdate as date) = DATEADD(day, 1, cast(ca1.enddate as date));
I also replaced the implicit join with improved join syntax.
If you're using SQL 2012 try the lag functions.
select distinct
ca1.StaffID,
ca1.EndDate,
ca1.ProjectDepartment as New_DeptID,
LAG(ca1.ProjectDepartment) OVER (PARTITION BY ca1.StaffId ORDER BY ca1.EndDate) as Prev_DeptID
from
emp_hist as ca1
If you're not, use the RANK function and a subquery
select
eh.StaffID,
eh.EndDate,
eh.ProjectDepartment as New_DeptID,
eh1.ProjectDepartment as Prev_DeptID
from
(select *, RANK(EndDate) OVER (PARTITION BY StaffId ORDER BY EndDate) as Rank
from emp_hist) eh left join (
select distinct
StaffID,
EndDate,
ProjectDepartment,
RANK(EndDate) OVER (PARTITION BY StaffId ORDER BY EndDate) as Rank
from
emp_hist) eh1 on eh1.staffid=a.staffid and eh1.rank=eh.rank-1

Count two Columns with two Where Clauses

I know it's just late in the day and my brain is just fried....
Using Teradata, I need to COUNT DISTINCT MEMBERS that haven't had a TRANS in the past six months and also COUNT the number of TRANS they had historically (prior to the six months). We can just assume the cutoff date to be 01/01/2012. All table is contained in a single table.
For example:
Member | Tran Date
123 | 01/01/2011
789 | 06/01/2011
123 |10/31/2011
678 | 04/03/2011
789 | 06/01/2012
So 2 members had a total of 3 transactions dated prior to 1/1/2012 with no transactions later than 1/1/2012.
In this example, my result would be:
MEMBERS | TRANS
2 | 3
Try this solution:
SELECT
COUNT(DISTINCT member_id) AS MEMBERS,
COUNT(*) AS TRANS
FROM
tbl
WHERE
member_id NOT IN
(
SELECT DISTINCT member_id
FROM tbl
WHERE trans_date > '2012-01-01'
)
You can't do it in one SQL statement. Use subqueries. This is TSQL coz I am unfamiliar with Teradata.
DECLARE #CUTOFF DATETIME = DATEADD(MO,-6,GETDATE()) --6MTHS AGO
SELECT COUNT(MEMBERID) AS MEMBERS, SUM(TRANSCOUNT) AS TRANS FROM (
SELECT DISTINCT
MEMBERID,
(SELECT COUNT(*) TRANSDATE WHERE TRANSDATA.MEMBERID = MEMBER.MEMBERIF) AS TRANSCOUNT
FROM MEMBER WHERE NOT EXISTS
(SELECT * FROM TRANSDATA, MEMBER WHERE
TRANSDATA.MEMBERID = MEMBER.MEMBERIF
AND TRANDATE > #CUTOFF)
)