MySQL query to retrieve DISTINCT COUNT between moving DATE period - mysql

I'm trying to write a query that returns a list of dates and the DISTINCT COUNT of User IDs for the 7 days preceding each date. The table I'm working with is simple, and looks like this:
Started UserId
"2012-09-25 00:01:04" 164382
"2012-09-25 00:01:39" 164382
"2012-09-25 00:02:37" 166121
"2012-09-25 00:03:35" 155682
"2012-09-25 00:04:18" 160947
"2012-09-25 00:08:19" 165806
I can write the query for output of an individual COUNT as follows:
SELECT COUNT(DISTINCT UserId)
FROM Session
WHERE Started BETWEEN '2012-09-18 00:00' AND '2012-09-25 00:00';
But what I'm trying to do is output this COUNT for every day in the table AND the 7 days preceding it. To clarify, the value for September 25th would be the count of DISTINCT User IDs between the 18th and 25th, the 24th the count between 17th and 24th, etc.
I tried the following query but it provides just the COUNT for each day:
SELECT
DATE(A.Started),
Count(DISTINCT A.UserId)
FROM Session AS A
WHERE DATE(A.Started) BETWEEN DATE(DATE_SUB(DATE(DATE(A.Started)),INTERVAL 7 DAY)) AND DATE(DATE(A.Started))
GROUP BY DATE(A.Started)
ORDER BY DATE(A.Started);
And the output looks like this:
DATE(A.Started) "Count(DISTINCT A.UserId)"
2012-09-18 709
2012-09-19 677
2012-09-20 658
2012-09-21 556
2012-09-22 530
2012-09-23 479
2012-09-24 528
2012-09-25 480
...
But as I said, those are just the daily counts. Initially I thought I could just sum the 7 day values, but that will invalidate the DISTINCT clause. I need the DISTINCT UserId counts for each 7 day period preceding a given date.

This query should work for you:
SELECT
DATE_FORMAT(d1.Started, '%Y-%m-%d') AS Started,
COUNT(DISTINCT d2.UserID) Users
FROM
(
SELECT
DATE(Started) AS Started
FROM
Session
GROUP BY
DATE(Started)
) d1
INNER JOIN
(
SELECT DISTINCT
DATE(Started) AS Started,
UserID
FROM
Session
) d2
ON d2.Started BETWEEN d1.Started - INTERVAL 7 DAY AND d1.Started
GROUP BY
d1.Started
ORDER BY
d1.Started DESC
Visit http://sqlfiddle.com/#!2/9339c/5 to see this query in action.

try:
Select Distinct Date(A.Started), Count(B.UserId)
From Session a
Join Session b
On b.Start Between AddDate(A.Start, day, -7) And A.Start
I'm not a MySQL guy, so the syntax might not be correct, but the pattern will work....

Related

Getting the number of users for this year and last year in SQL

My table is like this:
root_tstamp
userId
2022-01-26T00:13:24.725+00:00
d2212
2022-01-26T00:13:24.669+00:00
ad323
2022-01-26T00:13:24.629+00:00
adfae
2022-01-26T00:13:24.573+00:00
adfa3
2022-01-26T00:13:24.552+00:00
adfef
...
...
2021-01-26T00:12:24.725+00:00
d2212
2021-01-26T00:15:24.669+00:00
daddfe
2021-01-26T00:14:24.629+00:00
adfda
2021-01-26T00:12:24.573+00:00
466eff
2021-01-26T00:12:24.552+00:00
adfafe
I want to get the number of users in the current year and in previous year like below using SQL.
Date Users previous_year
2022-01-01 10 5
2022-01-02 20 15
The code is written as follows.
select CAST(root_tstamp as DATE) as Date,
count(DISTINCT userid) as users,
count(Distinct case when CAST(root_tstamp as DATE) = dateadd(MONTH,-12,CAST(root_tstamp as DATE)) then userid end) as previous_year
FROM table1
But it returns 0 for previous_year values.
How can I fix that?
Possible solution for SQL Server:
WITH cte AS ( SELECT 2022 [year]
UNION ALL
SELECT 2021 )
SELECT cte.[year],
COUNT(DISTINCT test.userId) current_users_amount,
COUNT(DISTINCT CASE WHEN YEAR(test.root_tstamp) < cte.[year]
THEN test.userId
END) previous_users_amount
FROM test
JOIN cte ON YEAR(test.root_tstamp) <= cte.[year]
GROUP BY cte.[year]
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=88b78aad9acd965bdbac4c85a0b81927
This query (for MySql) returns unique number of userids where the root_timestamp is in the current year, by day, and the number of unique userids for the same day last year. If there is no record for a day in the current year nothing will be displayed for that day. If there are rows for the current year, but no rows for the same day last year, then NULL will be shown for that lastyear column.
SELECT cast(ty.root_tstamp as date) as Dte,
COUNT(DISTINCT ty.userId) as users_this_day,
count(distinct lysd.userid) as users_sameday_lastyear
FROM test ty
left join
test lysd
on cast(lysd.root_tstamp as date)=date_add(cast(ty.root_tstamp as date), interval -1 year)
WHERE YEAR(ty.root_tstamp) = year(current_date())
GROUP BY Dte
If you wish to show output rows for calendar days even if there are no rows in current year and/or last year, then you also need a calendar table to be introduced (let's hope that it is not what you need)

MySQL query using count() and if/case

I need to find the count of users who have filled the questionnaire on that day.
These are the total counts , i need counts per day. Here is the picture of database: http://www.upload.ee/image/3800828/pildike.png
SELECT DISTINCT USER_ID, COUNT(ANSWER_TIME) AS ARV FROM RESULT WHERE ANSWER_TIME IS NOT NULL GROUP BY USER_ID ORDER BY ARV DESC;
For example this gives me:
32 2142
143 1098
26 979
76 878
But i need like distinct rows, answer_day_of_week is from 1 to 7, depending on day and answer_time is TIMESTAMP. The statistics is been for 97 days and for example person 32 has filled it 2000+ times in 97 days, but i only need to count them once...
I thought to use if-elseif or while or case or some sort of subquery ? I have tried some queries but i always fail...
For example for one day i can have 15 rows from one person on 1. oct but have 0 rows on 2. oct , then it gives answer that he has filled the survey only once.
SELECT USER_ID, COUNT(ARV) AS ARV
FROM
(
SELECT DISTINCT USER_ID, DATE(ANSWER_TIME) AS ARV FROM RESULT WHERE ANSWER_TIME IS NOT NULL
) A
GROUP BY USER_ID ORDER BY ARV DESC;
Please try the above query
Just change your sql query like this:
SELECT DISTINCT USER_ID, COUNT(ANSWER_TIME) AS ARV FROM RESULT WHERE DATE(ANSWER_TIME) >= DATE_SUB(CURDATE(), INTERVAL '97 DAYS') GROUP BY USER_ID ORDER BY ARV DESC;

MySQL : Count row where sum of left day is less than 30

I want to count the users in the table who's subscriptions are going to expire within a month (30 days). Here is my code:
user_db
id name exp_date
1 John 2013-03-01
2 Alice 2013-02-25
3 Ken 2013-01-10
4 Elise 2013-04-11
5 Bruce 2013-03-14
According to the DB above. There should be 3 persons whom their subscription is about to be expired - John, Alice and Bruce. I don't want Ken to be counted because he doesn't want to subscribe for more.
Here's my MySQL code:
SELECT count(id) AS exp_pax,
datediff(exp_date,now()) AS day_left
FROM labour_db
WHERE day_left<=30
Well, the code does selects only a row in which the sum of day less than 30 but it doesn't count. So please you guy suggest me.
Regards,
If you want to count all records where (1) the expiration date is within 30 days of now and (2) the expiration date is not before now, then use
SELECT count(*) AS exp_pax
FROM user_db
WHERE exp_date<=timestampadd(day, 30, now())
AND exp_date >= now();
If that's the case then you need to add condition wherein it checks if the exp_date is less than today.
SELECT COUNT(*) totalCount
FROM user_db
where exp_date <= timestampadd(day, 30, now()) AND
exp_date > NOW()
SQLFiddle Demo
Remove the group by id to get your count.
Count will roll up rows, as you expect, but when combined with a group by clause, will count each "group". You could use this usefully, for instance, to group by expiration date.

find out how many people registered each day

In mySQL what I am trying to do is to query my table and find out how many people registered each day. In other words, I want to be able to produce the following output for one month:
1 January: 10 registrations
2 January: 150 registrations
3 January: 50 registrations
select created, regID
from registrations
Dates are in the following format in the DB: 2012-11-01 00:00:00
To get registration counts for each day of January, use this select:
select daymonth(registration_date), count(*)
from registrations
where registration_date >= '01/01/2012' and registration_date <= '01/31/2012'
group by daymonth(registration_date)
You usually use a grouping operator:
SELECT COUNT(*) AS registrations, DATE(created) AS created_date GROUP BY created_date
If created is already a DATE column, then the conversion isn't required.
Try this:
SELECT created, count(regID) FROM registrations GROUP BY created ORDER BY created ASC
SELECT DATE(DATE_REGISTERED) DATE, COUNT(*) totalRegistered
FROM tableName
GROUP BY DATE

Average of a distinct count by day in Access

I'm trying to get an average of a distinct count per day out of an Access 2010 database and nothing I do seems to be working. I've tried using a subquery but I can't figure out how to link it to the main one. The table has a row for every office visit, like this:
patient_id, visit_year, visit_date, dow, doctor_id
12345, 2012, 3/5/12, Monday, 987
12567, 2012, 3/5/12, Monday, 986
12789, 2012, 3/6/12, Tuesday, 987
I need to get the average number of doctors available per day of week where year = 2012. In my head this should work but it doesn't:
Select dow, AVG(COUNT(DISTINCT(doctor_id))) AS AvgDocsInOffice
From visits
WHERE visit_year = 2012
GROUP BY dow
I'm trying to get to this output:
DOW, AvgDocsInOffice
Monday, 5
Tuesday, 6
Wednesday, 4
Any ideas? Unfortunately I'm stuck doing this in Access.
SELECT dow, AVG(CntDocsInOffice) AS AvgDocsInOffice FROM
(SELECT dow, visit_date, COUNT(*) AS CntDocsInOffice FROM
(SELECT DISTINCT dow, visit_date, doctor_id FROM
visits
WHERE visit_year = 2012)
GROUP BY dow, visit_date)
GROUP BY dow;
The inner most SELECT selects unique doctors per day.
The next outer SELECT counts the number of unique doctors per day.
The outer most SELECT finally calculates the average doctor count per day of week.
How about:
SELECT q.dow,
Avg(q.countofdoctor_id) AS avgofcountofdoctor_id
FROM (SELECT v.visit_date,
v.dow,
COUNT(v.doctor_id) AS countofdoctor_id
FROM (SELECT DISTINCT visit_date,
dow,
doctor_id
FROM visits
WHERE visit_year = 2012) AS v
GROUP BY v.visit_date,
v.dow) AS q
GROUP BY q.dow;