help optimize sql query - sql

I have tracking table tbl_track with id, session_id, created_date fields
I need count unique session_id for one day
here what i got:
select count(0)
from (
select distinct session_id
from tbl_track
where created_date between getdate()-1 and getdate()
group by session_id
)tbl
im feeling that it could be better solution for it

select count(distinct session_id)
from tbl_track
where created_date between getdate()-1 and getdate()

Why not just do exactly what you ask for?
select count(distinct session_id)
from tbl_track
where created_date between getdate()-1 and getdate()

Related

find people who have values in a specific date range but not in others

I am querying a User based database, and trying to find people that have made purchases withing a certain date range only.
e.g:
bring back all the people that purchased only between '2017-7-01' and '2017-08-01' but have not purchased since.
I have tried:
select payment_id
from table1
where created_at between '2017-7-01'
and '2017-08-01'
and not between '2017-7-01' and '2017-08-01';
and all kinds of variations on this.
I guess a subquery is in order here, but don't really know how to approach
hope someone can help :)
Thanks
select payment_id
from (
select payment_id
from table1
where created_at between '2017-7-01' and '2017-08-01' )
where created_at > '2017-08-01'
Use conditional COUNT() to see if user have any purchase in that date range and no purchase after the upper range limit.
Also you need something related to users, I guess user_id so you can group everything.
SELECT user_id
FROM yourTable
GROUP BY user_id
HAVING COUNT(CASE WHEN created_at between '2017-07-01'
and '2017-08-01'
THEN 1
END) > 0
AND COUNT(CASE WHEN created_at > '2017-08-01'
THEN 1
END) = 0
Select userid
From table1
Where userid not in (select userid from table1 where createdat between #startdate and #enddate)
Where createdat > #enddate
If you want to filter ensuring the MAX(date) is less than 2017-08-01 then you can use GROUP BY with HAVING.
Ex.
select payment_id
from table1
where created_at between '2017-07-01' AND '2017-08-01'
GROUP BY payment_id
HAVING MAX(created_at) < '2017-08-01' --most recent date less than requested date

Check if timestamp is contained in date

I'm trying to check if a datetime is contained in current date, but I'm not veing able to do it.
This is my query:
select
date(timestamp) as event_date,
count(*)
from pixel_logs.full_logs f
where 1=1
where event_date = CUR_DATE()
How can I fix it?
Like Mikhail said, you need to use CURRENT_DATE(). Also, count(*) requires you to GROUP BY the date in your example. I do not know how your data is formatted, but one way to modify your query:
#standardSQL
WITH
table AS (
SELECT
1494977678 AS timestamp_secs) -- Current timestamp (in seconds)
SELECT
event_date,
COUNT(*) as count
FROM (
SELECT
DATE(TIMESTAMP_SECONDS(timestamp_secs)) AS event_date,
CURRENT_DATE()
FROM
table)
WHERE
event_date = CURRENT_DATE()
GROUP BY
event_date;

SQL Server: Attempting to output a count with a date

I am trying to write a statement and just a bit puzzled what is the best way to put it together. So I am doing a UNION on a number of tables and then from there I want to produce as the output a count for the UserID within that day.
So I will have numerous tables union such as:
Order ID, USERID, DATE, Task Completed.
UNION
Order ID, USERID, DATE, Task Completed
etc
Above is layout of the table which will have 4 tables union together with same names.
Then statement output I want is for a count of USERID that occurred within the last 24 hours.
So output should be:
USERID--- COUNT OUTPUT-- DATE
I was attempting a WHERE statement but think the output is not what I am after exactly, just thinking if anyone can point me in the right direction and if there is alternative way compared to the union? Maybe a joint could be a better alternative, any help be appreciated.
I will eventually then put this into a SSRS report, so it gets updated daily.
You can try this:
select USERID, count(*) as [COUNT], cast(DATE as date) as [DATE]
from
(select USERID, DATE From SomeTable1
union all
select USERID, DATE From SomeTable2
....
) t
where DATE <= GETDATE() AND DATE >= DATEADD(hh, -24, GETDATE())
group by USERID, cast(DATE as date)
First, you should use union all rather than union. Second, you need to aggregate and use count distinct to get what you want:
So, the query you want is something like:
select count(distinct userid)
from ((select date, userid
from table1
where date >= '2015-05-26'
) union all
(select date, userid
from table2
where date >= '2015-05-26'
) union all
(select date, userid
from table3
where date >= '2015-05-26'
)
) du
Note that this hardcodes the date. In SQL Server, you would do something like:
date >= cast(getdate() - 1 as date)
And in MySQL
date >= date_sub(curdate(), interval 1 day)
EDIT:
I read the question as wanting a single day. It is easy enough to extend to all days:
select cast(date as date) as dte, count(distinct userid)
from ((select date, userid
from table1
) union all
(select date, userid
from table2
) union all
(select date, userid
from table3
)
) du
group by cast(date as date)
order by dte;
For even more readability, you could use a CTE:
;WITH cte_CTEName AS(
SELECT UserID, Date, [Task Completed] FROM Table1
UNION
SELECT UserID, Date, [Task Completed] FROM Table2
etc
)
SELECT COUNT(UserID) AS [Count] FROM cte_CTEName
WHERE Date <= GETDATE() AND Date >= DATEADD(hh, -24, GETDATE())
I think this is what you are trying to achieve...
Select
UserID,
Date,
Count(1)
from
(Select *
from table1
Union All
Select *
from table2
Union All
Select *
from table3
Union All
Select *
from table4
) a
Group by
Userid,
Date

Get Count of users based on date

I have simple table where i store userID, UserName, Email, RegistrationDate ...
RegistrationDate is DateTime Datatype
When i to to get the count of users for each date it get me 1 for each row as it each row has a unique dateTime stamp.
SELECT DATEPART(dd, RegistrationDate) AS DD, COUNT(userID)
FROM USER_Table
GROUP BY RegistrationDate
order by RegistrationDate DESC
ABove query get me each 100 rows if i have 100 users registered.
I want to get count based on date. i tried different thing but nothing seems to work.
Try this :
SELECT Cast(RegistrationDate AS DATE),
Count(userID)
FROM User_Table
GROUP BY Cast(RegistrationDate AS DATE)
ORDER BY Cast(RegistrationDate AS DATE)DESC
You need to group by CAST(RegistrationDate as Date)
SELECT CAST(RegistrationDate as Date) AS [Date], COUNT(userID)
FROM USER_Table
GROUP BY CAST(RegistrationDate as Date)
order by CAST(RegistrationDate as Date) DESC
SELECT cast(RegistrationDate as Date) AS DD, COUNT(userID)
FROM USER_Table
GROUP BY cast(RegistrationDate as Date)
order by cast(RegistrationDate as Date) DESC

SQL grouping user count by Mondays

Given a Users table like so:
Users: id, created_at
How can I get the # of users created grouped by day? My goal is to see the number of users created this Monday versus previous Monday's.
If created_at is of type timestamp, the simplest and fastest way is a plain cast to date:
SELECT created_at::date AS day, count(*) AS ct
FROM users
GROUP BY 1;
Since I am assuming that id cannot be NULL, count(*) is a tiny bit shorter and faster than count(id), while doing the same.
If you just want to see days since "last Monday":
SELECT created_at::date, count(*) AS ct
FROM users
WHERE created_at >= (now()::date - (EXTRACT(ISODOW FROM now())::int + 6))
GROUP BY 1
ORDER BY 1;
This is carefully drafted to use a sargable condition, so it can use a simple index on created_at if present.
Consider the manual for EXTRACT.
SELECT COUNT(id) AS cnt, EXTRACT(DOW FROM created_at) AS dow
FROM Users
GROUP BY EXTRACT(DAY FROM created_at)
If you want to see the days, use to_char(<date>, 'Day').
So, one way to do what you want:
select date_trunc('day', created_at), count(*)
from users u
where to_char(created_at, 'Dy') = 'Mon'
group by date_trunc('day', created_at)
order by 1 desc;
Perhaps a more general way to look at it would be to summarize the results by day of the week, for this week and last week. Something like:
select to_char(created_at, 'Day'),
sum(case when created_at >= current_date - 6 then 1 else 0 end) as ThisWeek,
sum(case when trunc(created_at) between current_date - 13 and current_date - 7 then 1 else 0 end) as LastWeek
from users u
group by to_char(created_at, 'Day')
I am from a T-SQL background and I would do something like this
CREATE TABLE #users
(id int,
created_at datetime
)
INSERT INTO #users
(id, created_at)
VALUES
(
1, getdate()
)
INSERT INTO #users
(id, created_at)
VALUES
(
1, getdate()
)
INSERT INTO #users
(id, created_at)
VALUES
(
1, dateadd(DAY, 1,getdate())
)
SELECT id, created_at, count(id) FROM #users
GROUP BY id, created_at
DROP TABLE #users
You will get better results if you only group by day part and not the entire datetime value.
Coming to second part - only comparing for Mondays; you can use something like
select datename(dw,getdate())
the above will give you the name of the weekday which you can compare against a string literal 'Monday'.