how to get transactions on a database for a specific time - sql

I want to get the users from a postgresql database where users activity is not seen for a specific period of time etc. (Basically I am trying to get which users who are not using the application at all)
For example the following SQL query is for users not using for the last 30 days:
SELECT distinct on (username) username, started_at
FROM projects_user JOIN projects_synclog
ON projects_user.id = projects_synclog.user_id
WHERE started_at BETWEEN '2019-08-15' AND '2019-09-15'
ORDER BY username, started_at DESC
In this query it is showing all the users which means for example a user may have logged in a month ago for once and again the same user has logged in 2 days ago. In this case, the user is still active, which I don't want to be listed out.
I have been trying this for countless hours. I searched for solutions a lot in here and other forums listed in google.
I would highly appreciate any help.
Thanks a lot.

I think you want aggregation and having. This answers the question in the title:
SELECT pu.username, max(sl.started_at)
FROM projects_user pu LEFT JOIN
projects_synclog sl
ON pu.id = sl.user_id
GROUP BY pu.username
HAVING MAX(sl.started_at) IS NULL OR
MAX(sl.started_at) < CURRENT_DATE - INTERVAL '7 DAY'

Related

sql query to find specific entries based on date range

I have a database with a table containing the history of the login times of all accounts. The table includes columns USERID and LOGIN_DATE. I want to find those users who have not logged in for over 60 days, so an SQL query that says
Find users who have a login date which was greater than 60 days ago, but have no entry for any date more recently than 60 days ago
Can anyone suggest how I would do this ?
Following can be a solution
select USERID, min(login_date) mind, max(login_date) maxd
from Logins
group by UserId
having max(login_date) < dateadd(d,-60,getdate())
You could use aggregation, and filter on users whose maximum login date is older than 60 days:
select userid
from mytable
group by userid
having max(login_date) < current_date - interval '60' day
You did not tell which database you are using, so this uses standard date arithmetics. You might need to adapt that to your actual database (all major databases have alternatives for this).
Now the question was tagged Oracle. The above would work; you might want to truncate the time portion of the date to check on entire days. And if you want to display the last login, just add the aggregate function to the select clause:
select userid, max(login_date) last_login_date
from mytable
group by userid
having max(login_date) < trunc(current_date) - interval '60' day
You can use aggregation:
select userid
from t
group by userid
having max(logindate) < trunc(sysdate) - interval '60' day;
Date/time functions are notoriously database-specific, so the exact syntax for the having clause might depend on your database.

Resolving "Failed to parse input string" error in BigQuery

I'm working on a cohort analysis where I count the number of users who signed up by week, then count the number of events each perform over subsequent weeks. (Pretty standard stuff!)
After spending a lot of time understanding BigQuery nesting and array data, I decided to create two views to flatten nested user_dim and event_dim columns using wildcard over the entire data set (tables generated of events on a daily basis). That's how I wound up with these views, on which my query is based:
USERS_VIEW schema
EVENT_VIEW schema
Query, and the Error Thrown
When I execute the following query joining those two views, I get the error "Failed to parse input string "20161111"":
SELECT
DATE_TRUNC(users.first_seen_date, WEEK) AS week,
COUNT(DISTINCT users.uid) AS signed_up_users,
COUNT(DISTINCT events.uid) AS logged_in_users,
CASE
WHEN COUNT(DISTINCT users.uid) > 0 THEN COUNT(DISTINCT events.uid) * 100 / COUNT(DISTINCT users.uid)
ELSE 0
END AS retention_pct
FROM
USERS_VIEW AS users
LEFT JOIN
EVENTS_VIEW AS events
ON
users.uid = events.uid
AND PARSE_DATE('%x', events.event_date) >= DATE_ADD(users.first_seen_date, INTERVAL 1 WEEK)
AND PARSE_DATE('%x', events.event_date) < DATE_ADD(users.first_seen_date, INTERVAL 2 WEEK)
GROUP BY
1
ORDER BY
1
I feel like this should be simple, but I can't figure out what formatting I'm missing to ensure the dates can be parsed. (And the UI doesn't tell me which line number is the offender.) I'm hoping it's a silly typo that someone else can see. Thanks in advance for any help!
I get the error "Failed to parse input string "20161111""
I think below will help to address that error
PARSE_DATE('%x', events.event_date)
should be
PARSE_DATE('%Y%m%d', events.event_date)
Also, optionally, you might want to change LEFT JOIN to just JOIN

SQL - How to find records older than x days and not occurs after x days

I have a table with logging records (login_time, user_name) and I need to find records which are older than 90 days and didn't occur after this time.
So it will be a list of users that for eg. has been visiting my page several times but from some reasons they stopped.
I have query only for listing records older than 90 days and I don't know waht to put next.
SELECT
"u_user_name",
"login_time"
FROM
table
WHERE
"login_time" < now()-interval'90'day
Thanks in advance
Nullo
You can do something like this:
SELECT u_user_name, max(login_time) as most_recent_login_time
FROM table t
GROUP BY u_user_name
HAVING MAX(login_time) < now() - interval '90' day;

How can I run this except sub-query in one single query?

I am using postgreSQL, I have two tables, one is user, and one is usertasks.
user has following fields : userid, username
usertasks has following fields: id, taskdate, userid
userid and id are primary keys on above tables
I want to find all users who have made less than 3 tasks in last 3 months.
I cannot use WHERE taskdate>(last3months) here because I need all the users, not just those who made tasks in last 3 months. (Some users might have done their tasks 6 months ago, but didn't do any task in last 3 months, so I need those users as well)
My query is this:
select userid
from users
EXCEPT
select userid from usertasks
where usertasks.taskdate > CURRENT_DATE - INTERVAL '3 months'
group by usertasks.userid having count(id) >= 3
Problem:
The above query works perfectly and returns the right result, I have also tried NOT IN , instead of EXCEPT, that works fine too, but the thing is I am getting performance issues, can this be done in one single query without using a sub query, can it be done using joins or any other method ? The use of sub-queries making it slower.
the test case is for 100 thousand users and 1 million tasks, i am searching for fastest methods..
You need to use having with a case.
Select u.user_id
from users u
left join usertask ut
on ut.user_id=u.user_id
group by u.user_id
having count(case when ut.taskdate > CURRENT_DATE - INTERVAL '3 months' then task_id else null end)<3 -- count of tasks in last 3 monthx < 3

SQL get users within range

I've got a database that stores when users subscribed and unsubscribed from a service. What I want to do is see who unsubscribed each month, and then see how many of those people had unsubscribed within 30 days of subscribing. I have two fields, DateJoined_ and DateUnsub_ that both return a smalldatetime. How would I be able to find these people using DateJoined and DateUnsub? I know I have to do some sort of calculation, and I could do this easily if I wasn't using SQL - any suggestions?
SELECT *
FROM UserTable
WHERE DATEDIFF(day, DateJoined, DateUnSub) <= 30
http://msdn.microsoft.com/en-us/library/ms189794.aspx
What DBMS are you using? For MySQL:
select * from table where DATEDIFF(DateUnsub_, DateJoined_) <= 30
As for getting the number of users who unsubscribed each month, you could GROUP BY DATEPART(year, DateUnsub_), DATEPART(month, DateUnsub_) or instead limit on those dateparts to get the list of users.
http://msdn.microsoft.com/en-us/library/ms174420.aspx