Users that returned - sql

I have a table with [EVENT_DATE] and [USER_ID], I would like to know how to count the users who came back in the same month.
Table_01
-------------------------------------------
EVENT_DATE | USER_ID
-------------------------------------------
2017-03-28 00:00:25.000 | 0006235012201
2017-03-04 23:00:00.000 | 0006235012201
2017-03-19 00:25:15.000 | 0006235012201
2017-02-03 10:00:02.000 | 0006235012202
2017-01-18 00:15:00.000 | 0006235012202
2017-03-28 11:00:15.000 | 0006235012202
2017-03-23 15:20:02.000 | 0006235012203
2017-02-18 12:00:06.000 | 0006235012203
2017-03-21 16:05:09.000 | 0006235012203
The answering being 2, because users 0006235012201 & 0006235012203 both came back within the same month.
EDIT: Sorry
I am looking to get the count by month.
-----------------------
Month | Users Returned
-----------------------
01/17 | 70
02/17 | 60
03/17 | 10
This is what I have, but it isn't correct as it seems to be listing users.
SELECT A.[USER_ID], A.[EVENT_DATE], COUNT(*)
FROM(
SELECT [USER_ID], [EVENT_DATE], COUNT(*)
FROM Table_01
GROUP BY [USER_ID], [EVENT_DATE]
HAVING COUNT(*) > 1
) A
GROUP BY A.[USER_ID], A.[EVENT_DATE]
Microsoft SQL Server 2016. Compatibility level: SQL Server 2005 (90)

select user_id
from your_table
group by user_id
having count(distinct year(event_date) * 100 + month(event_date)) > 1

Try the below script
SELECT DISTINCT USER_ID
FROM Table_01
GROUP BY USER_ID, (YEAR(EVENT_DATE)*100)+MONTH(EVENT_DATE)
HAVING COUNT(*) > 1

Use below query to get users returned in same month
SELECT USER_ID
FROM #Table
GROUP BY USER_ID,(YEAR(EVENT_DATE)*100)+MONTH(EVENT_DATE)
HAVING COUNT(*) > 1

Using this you can get month wise result
select month(EVENT_DATE),year(EVENT_DATE), USER_ID from tableName
where year(EVENT_DATE)=2017
Group by USER_ID,year(EVENT_DATE),month(EVENT_DATE)
Having HAVING COUNT(*) > 1
if you want some specific month wise you can add where condition like month(EVENT_DATE) =3

You need two levels of aggregation. First to get the users who have more than one row in a month. Then grouping by year,month to get the counts of users for a specific month.
select cast(mth as varchar(2))+'/'+cast(yr as varchar(4)) as mth,count(*)
from (select user_id,month(event_date) as mth,year(event_date) as yr
from tablename
group by user_id,month(event_date),year(event_date)
having count(*) > 1
) t
group by cast(mth as varchar(2))+'/'+cast(yr as varchar(4))

Related

SQL Query to get the distinct dates which are at least 10 days apart

I have a table which consists of dates and names. I want to group the result by names and dates with a condition that the resultant dates selected are at least 10 days apart. (starting from first date present in the table for that name)
This is an example:
________________________
Names | Dates
-----------------------
John | 2-2-2000
________________________
John | 5-2-2000
________________________
John | 16-2-2000
________________________
John | 17-2-2000
________________________
John | 20-2-2000
________________________
John | 31-2-2000
________________________
John | 5-3-2000
________________________
John | 14-3-2000
________________________
The output of the query should be the sum of count of these values (John,2-2-2000),(John,16-2-2000),(John,31-2-2000),(John,14-3-2000) That is, 4.
How do I write a query in SQL Server for this?
This is a bit tricky, because you need to keep track of the last row that was "picked" to select the next one. This means that you need to kind of iterative process, which in turns suggests a recursive query:
with
data as (
select t.*, row_number() over(partition by names order by dates) rn
from mytable t
),
rcte as (
select d.*, dates dates_base from data d where rn = 1
union all
select
d.*,
case when d.dates >= dateadd(day, 10, r.dates_base) then d.dates else r.dates_base end
from rcte r
inner join data d on d.rn = r.rn + 1 and d.names = r.names
)
select names, count(distinct dates_base) res from rcte group by names
Demo on DB Fiddlde:
names | res
:---- | --:
John | 4
Your question is unclear. Also consistent with your desired results is that you want to count rows where the gap from the previous row is 10+ days. For that, simply use lag():
select count(*)
from (select t.*,
lag(date) over (partition by name) as prev_date
from t
) t
where prev_date is null or prev_date < dateadd(day, -10, date);
Use select * to get the list of records.

Count distinct dates within timestamp by Month SQL

I would like to count the number of distinct dates within each month.
I have a data set that looks like this:
TIMESTAMP
------------------
2017-10-25 14:39:51
2017-10-25 15:00:51
2017-11-10 02:39:42
2018-09-24 14:39:55
2018-09-25 13:25:01
2019-02-12 12:23:44
...
So my expected output would be:
year_month | count
2017-10 2
2018-09 2
2019-02 1
I have tried the following code so far, but it is returning incorrect results:
WITH F AS(
SELECT concat(YEAR(TIMESTAMP), MONTH(TIMESTAMP)) AS year_month
FROM tbl
WHERE TYPE = 'Site'
AND TO_SITE = 'location'
)
SELECT count(year_month), year_month
FROM F
GROUP BY year_month
I do not need to worry about the time of day. I just want to count the distinct days in each month. Thank you in advance for your help.
In SQL Server, I would recommend one of these approaches:
select year(timestamp), month(timestamp), count(distinct convert(date, timestamp)
from t
group by year(timestamp), month(timestamp);
Or:
select format(timestamp, 'yyyy-MM'), count(distinct convert(date, timestamp))
from t
group by format(timestamp, 'yyyy-MM');
I see no need for subqueries or CTEs.
from your code I assume you are using a SQL Server then you can do something like this
with cte as
(
select
left(convert(varchar, myCol,112),6) as yyyy_mm,
convert(date, myCol) as date
from myTable
)
select
yyyy_mm,
count(distinct date) as count
from cte
group by
yyyy_mm
output:
| yyyy_mm | count |
*-----------------*
| 201710 | 1 |
| 201711 | 1 |
| 201809 | 2 |
| 201902 | 1 |
Using date_trunc() in PostgreSQL it can simply be:
SELECT date_trunc('month', timestamp)
, count(DISTINCT date_trunc('day', timestamp))
FROM tbl
GROUP BY 1;
Various performance optimizations possible, depending on details of the setup.

Getting percentage value of records using the max count of records in SQL Server

I'm a newbie to SQL learner and I have an issue I'd like you all to help me with. I've got a table User_Activity_Log that contains the names of students with their ID (user_id), Date of Attendance in the year (User_timestamp) in the format (February 25,2015).
Say the User_Activity_Log table contains
| user_id | user_timestamp |
| jude | February 22 |
| jude | February 24 |
| annie | February 1 |
| sam | January |
I'd like to know how to get a table showing the User Id, the number of counts a student is seen in the month and the percentage count, which should be gotten from the max(count) of a student.
Here's what I've done so far, this gives me error.
USE FinalYearProject
declare #maxval int
select
#maxval = (SELECT MAX(fromsubq.SM) as PA
FROM
(SELECT COUNT (user_Id) as SM
FROM dbo.User_Activity_Log
WHERE user_Timestamp LIKE 'February%'
GROPU BY User_Id) fromsubq
)
(SELECT COUNT
FROM dbo.User_Activity_Log
WHERE user_Timestamp like 'February%'
GROUP BY user_Id) * 100.0 / #maxval
Expected output should be
| User_id | Count | PercentageCount |
| Jude | 2 | 100 % |
| annie | 1 | 50 % |
| sam | 0 | 0 % |
Please help me point out the problem and possible solutions
Thanks in advance.
You can do this by using conditional aggregation in a subquery/cte and adding OVER() to an aggregate:
;with cte AS (SELECT User_ID
,SUM(CASE WHEN user_timestamp LIKE 'February%' THEN 1 ELSE 0 END) as CT
FROM User_Activity_Log
GROUP BY User_ID
)
SELECT User_ID
,CT
,CT*100.0 / MAX(CT) OVER() AS PercentageCount
FROM cte
ORDER BY CT DESC
Demo: SQL Fiddle
Note: It's bad practice to store dates as strings, if you can avoid it at all you should.
Edit: Here's how it would be done with a subquery instead of cte:
SELECT User_ID
,CT
,CT*100.0 / MAX(CT) OVER() AS PercentageCount
FROM (SELECT User_ID
,SUM(CASE WHEN user_timestamp LIKE 'February%' THEN 1 ELSE 0 END) as CT
FROM User_Activity_Log
GROUP BY User_ID
) AS Sub
ORDER BY CT DESC
UPDATE: To use the PercentageCount in a CASE expression, something like:
;with cte AS (SELECT User_ID
,SUM(CASE WHEN user_timestamp LIKE 'February%' THEN 1 ELSE 0 END) as CT
FROM User_Activity_Log
GROUP BY User_ID
)
,cte2 AS (SELECT User_ID
,CT
,CT*100.0 / MAX(CT) OVER() AS PercentageCount
FROM cte
)
SELECT *,CASE WHEN PercentageCount > .5 THEN 'Qualified' ELSE 'NotQualified' END AS Qualified
FROM cte2
ORDER BY CT DESC
First find the Count per user_id in sub-select then find the the percentage in outer query.
Use max over() to find the max value in count then divide each count by max count to get the percentage. Try this.
SELECT user_Id,
Cnt AS [Count],
( Cnt / Max(Cnt) OVER() ) * 100 AS PercentageCount
FROM (SELECT Count(user_Id) AS Cnt,
user_Id,
FROM dbo.User_Activity_Log
WHERE user_Timestamp LIKE 'February%'
GROUP BY User_Id) A

Select top 2 rows different from each other

I have this table
| date | sum |
|--------------|-------|
| 2015-02-19 | 10000 |
| 2015-02-19 | 10000 |
| 2015-02-20 | 15000 |
| 2015-02-20 | 15000 |
| 2015-02-21 | 18000 |
| 2015-02-21 | 18000 |
I want to select top 2 rows from the table, but only different ones, meaning my result should return 2015-02-20 and 2015-02-21.
SELECT TOP 2 distinct date
FROM stock
Using this gives me an error:
Incorrect syntax near the keyword 'distinct'.
Help would be highly appreciated.
You can try like this
select top 2 * from
(
select distinct date FROM stock
)
Try something like:
SELECT TOP 2 date
FROM stock
GROUP BY date
I think Distinct and Top should switch places in your query:
SELECT DISTINCT TOP 2 date FROM stock ORDER BY date DESC
try
select distinct top 2 date from stock
You can use GROUP BY:
SELECT TOP 2 date
FROM stock
GROUP BY date
ORDER BY date DESC
Sample result:
DATE
2015-02-21
2015-02-20
See result in SQL Fiddle.
Try this :
WITH cte AS
( SELECT distinct date ,
ROW_NUMBER() OVER (PARTITION BY date
ORDER BY date DESC
)
AS rn
FROM stock
)
SELECT date
FROM cte
WHERE rn <= 3
ORDER BY rn ;
Try this:
SELECT TOP 2 date FROM stock group by date

Select Count Distinct

I would like to count the number of installations of each Member in a table similar to this. But this count distinct drives me nuts...
MemberID | InstallDate
1 | Yesterday
2 | Today
1 | Today
3 | Today
The above table should produce something like this one..
MemberID | CountNumberOfInstallations
1 | 2
2 | 1
3 | 1
p.s. I know it sound's like homework, but it isnt.
It looks like the query you are looking for is:
SELECT MemberID, COUNT(*)
FROM Table
GROUP BY MemberID
The DISTINCT keyword is not required. If order is required, you can use:
SELECT MemberID, COUNT(*)
FROM Table
GROUP BY MemberID
ORDER BY MemberID ASC