Change MySql value based on time that has past - mysql

I have the following table:
user_id post_streak streak_date streak first_name club_id
-------- ----------- ------------ --------- ----------- --------
18941684 1 2015-05-05 15:36:18 3 user 1000
I want to change streak to 0 if it has been longer then 12 days.
current query:
select
first_name, streak, user_id from myTable
where
club_id = 1000
and
post_streak = 1
and
streak_date between date_sub(now(),INTERVAL 12 DAY) and now()
order by streak desc;
Which doesn't show results older then 12 days. I want to show all results but change "streak" to 0 if it has been longer the 12 days.
What is the best way to go about this?

UPDATE table
SET (streak)
VALUES (0)
WHERE streak_date < DATEADD(DAY, -12, NOW() );
SELECT first_name, streak, user_id from myTable
WHERE
club_id = 1000
AND
post_streak = 1
ORDER BY streak DESC;
First query will set all streak values to 0 for records that have streak_date of more than 12 days ago
Second query will get a list of all your records that have a club_id of 1000 and a post_streak of 1

Put the condition in the select, rather than the where:
select first_name,
(case when streak_date between date_sub(now(), INTERVAL 12 DAY) and now()
then streak
else 0
end) as streak,
user_id from myTable
where club_id = 1000
order by streak desc;
I'm not sure if the post_streak condition is needed in the where clause.

http://sqlfiddle.com/#!9/d8bbd/6
select
user_id,
first_name,
streak_date,
IF(streak_date between date_sub(now(),INTERVAL 12 DAY) and now(),streak,0)
from myTable
where
club_id = 1000
and
post_streak = 1
order by streak desc;

Related

Query to get all users that have logged in within the last 30 days

I have a MySQL db users table that has a column called lastLogin this is just a simple timestamp to indicate when a user has last logged into the system.
e.g
id
name
lastLogin
accountId
2
bob
1639572638
4
3
tim
1639572638
4
3
ant
1639572638
5
4
leroy
1339572638
6
expected results
accountId
activeUsers
4
2
5
1
6
0
My current query returns 0 rows but not sure why
SELECT accountId, from_unixtime(lastLogin) as lastlogin, count(distinct(id)) as activeUsers
FROM user
HAVING lastlogin > now() - INTERVAL 30 day
ORDER BY lastlogin desc;
SELECT accountId,
FROM_UNIXTIME(MAX(lastlogin)) lastlogin, -- not listed in desired output
-- but present in the query
SUM(lastlogin > UNIX_TIMESTAMP(CURRENT_DATE - INTERVAL 30 DAY)) activeUsers
FROM user
GROUP BY accountId
For distinct id use
SELECT accountId,
FROM_UNIXTIME(MAX(lastlogin)) lastlogin,
COUNT(DISTINCT CASE WHEN lastlogin > UNIX_TIMESTAMP(CURRENT_DATE - INTERVAL 30 DAY) THEN id END) activeUsers
FROM user
GROUP BY accountId
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=f754e9ed49d872d0d68173a803f96126
Try this:
with u as
(select accountId, count(distinct id) as activeUsers from user
group by accountId
having FROM_UNIXTIME(max(lastlogin)) > now() - INTERVAL 30 day),
v as
(select distinct accountId from user)
(select v.accountId, coalesce(u.activeUsers, 0) as activeUsers from v left join
u on v.accountId = u.accountId)
Fiddle
okay i figured it out hopefully helps someone else -
SELECT accountId,count(distinct(id)) as activeUsers
FROM user
WHERE FROM_UNIXTIME(lastlogin) > now() - INTERVAL 30 day
GROUP BY accountId;

Show number of lower and higher values in SQL

I have a certain problem while trying to make an SQL. I have a table with the following format and data.
id
value
date
12
3
2020-06-01
12
4
2020-06-09
12
1
2020-06-20
5
4
2020-06-11
5
5
2020-06-17
My goal is to make something like that:
id
lower
higher
12
1
1
5
0
1
This looks for the value of the oldest row IN specific interval (ex. 100 days)and it compares it with all dates after that if their values are higher and lower and return the count.
I do have something that works but it requires more queries:
One to group take all ids with dates in the interval of xx days
SELECT id FROM table
WHERE date >= CURDATE() - INTERVAL 30 DAY GROUP BY id
ORDER BY id ASC;
And then I loop through each row and get its lower and higher values.
SELECT
*
FROM
(
SELECT
COUNT(*) AS higher, id
FROM
`table`
WHERE
id = 12 AND date > CURDATE() - INTERVAL 30 DAY AND value > (
SELECT value FROM table
WHERE table.date >= CURDATE() - INTERVAL 30 DAY AND id = 12
ORDER BY `table`.`date` ASC LIMIT 1
)
) AS t1,(
SELECT
COUNT(*) AS deteriorated_placements
FROM
`table`
WHERE
id = 12 AND date > CURDATE() - INTERVAL 30 DAY AND value < (
SELECT value FROM table
WHERE table.date >= CURDATE() - INTERVAL 30 DAY AND id = 12
ORDER BY `table`.`date` ASC LIMIT 1
)
) AS t2;
The problem with that is that I do around 40 more queries. I know it maybe is not a big issue but
Is there a way to somehow combine those 2 queries?
Use first_value():
select id,
sum(value < value_1) as lower,
sum(value > value_1) as higher
from (select t.*,
first_value(value) over (partition by id order by date) as value_1
from t
) t
group by id;

Count records which fulfil given condition

I have a table with the following schema:
+-------------------------------------------------------+
| table_counter |
+----+---------------------+------------+---------------+
| id | timestamp | entry_type | country |
+----+---------------------+------------+---------------+
+----+---------------------+------------+---------------+
| 10 | 2017-05-01 12:00:00 | click | Germany |
+----+---------------------+------------+---------------+
| 11 | 2017-05-01 12:00:00 | view | Austria |
+----+---------------------+------------+---------------+
| 12 | 2017-05-01 12:00:00 | click | UK |
+----+---------------------+------------+---------------+
| 13 | 2017-05-01 12:00:00 | view | USA |
+----+---------------------+------------+---------------+
I need to return the following result: Select the sum of views and clicks of the top 5 countries by sum of views in the past 30 days.
I know how to count the records all right, but how do I define the constrains? How do I return all entries from five countries with the highest number of views?
Limiting the result to the last 30 days is trivial, but I'm pretty much stuck at the beginning.
Using order by and limit keywords,
SELECT SUM(IF(entry_type = "view", 1, 0)) as view_count FROM t3 GROUP BY country, entry_type ORDER BY view_count DESC LIMIT 5
--EDIT
As per the requirement stated in the comments, here's the updated query:
SELECT SUM(view_click_count) as all_total FROM (SELECT country, SUM(IF(entry_type = "view", 1, 0)) as view_count, SUM(IF(entry_type = "click", 1, 0)) as click_count, count(entry_type) as view_click_count FROM t3 GROUP BY country ORDER BY view_count DESC LIMIT 5) t2
all_total gives the total count as needed, for top 5 countries.
You can do it this way:
select
tc.country,
count(case entry_type when 'click' then 1 else null end) clicks,
count(case entry_type when 'view' then 1 else null end) views
from table_counter tc
inner join (
select top 5 country from [dbo].[table_counter]
where entry_type = 'view'
and timestamp >= DATEADD(DAY, -30, GETDATE())
group by country
order by count(entry_type) desc
) t on t.country = tc.country
where timestamp >= DATEADD(DAY, -30, GETDATE())
group by tc.country
order by views desc
This is for SQL Server. A few tweaks might be needed for MySQL (i.e. 'Limit' instead of 'TOP')
You can get top 5 countries by views with the following query, e.g.:
SELECT country, count(*) as 'views'
FROM table
WHERE timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()
AND entry_type = 'view'
GROUP BY country
ORDER BY count(*) DESC
LIMIT 5
Now, to select clicks, you can add another query in SELECT , e.g.:
SELECT t.country, COUNT(*) as 'views',
(SELECT COUNT(*)
FROM `table`
WHERE country = t.country
AND entry_type = 'click'
AND timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()
) as 'clicks'
FROM `table` t
WHERE t.timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()
AND t.entry_type = 'view'
GROUP BY t.country
ORDER BY count(*) DESC
LIMIT 5
Here's the SQL Fiddle.
Update
To get the SUM of views and clicks, wrap the above query into another SELECT, e.g.:
SELECT country, views + clicks
FROM(
SELECT t.country, COUNT(*) as 'views',
(SELECT COUNT(*)
FROM `table`
WHERE country = t.country
AND entry_type = 'click'
AND timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()
) as 'clicks'
FROM `table` t
WHERE t.timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()
AND t.entry_type = 'view'
GROUP BY t.country
ORDER BY count(*) DESC
LIMIT 5
) b;
Here's the updated SQL Fiddle.

Sql query not returning max value

I have written the following query to get the value with the max issue_id. But I get the issue_id 14 for book_id 2. What I want is to get issue_id 16 when book_id is 2. And issue_id 15 when book_id is 3 and so on.
SELECT issue.issue_id AS issue_id, issue.issue_date, issue.student_id, books.availability,
CASE WHEN NOW() > DATE_ADD(issue.issue_date, INTERVAL 20 DAY)
THEN 10*DATEDIFF(NOW(), DATE_ADD(issue.issue_date, INTERVAL 20 DAY))
ELSE 0 END AS fine_amount
FROM issue
INNER JOIN books
ON issue.book_id=books.book_id
WHERE books.book_id=2
HAVING MAX(issue.issue_id)
Use the ORDER BY .. LIMIT 1 to get the highest value
SELECT issue.issue_id AS issue_id, issue.issue_date, issue.student_id, books.availability,
CASE WHEN NOW() > DATE_ADD(issue.issue_date, INTERVAL 20 DAY)
THEN 10*DATEDIFF(NOW(), DATE_ADD(issue.issue_date, INTERVAL 20 DAY))
ELSE 0 END AS fine_amount
FROM issue
INNER JOIN books
ON issue.book_id=books.book_id
WHERE books.book_id=2
ORDER BY issue.issue_id DESC LIMIT 1

MySQL: Is it possible to do this with a single query?

I am trying to perform two different SUMs within a single query.
user points date_achieved
-----------------------------
Foo 10 2000-01-01
Foo 20 2011-11-18
Bar 10 2000-01-01
Bar 20 2011-11-15
Bar 30 2011-11-18
1) Total points
SELECT user, SUM(points) AS points_total
FROM myTable
GROUP BY user
2) Points accumulated within the past month
SELECT user, SUM(points) AS points_month
FROM myTable
WHERE date_achieved >= CURRENT_DATE - INTERVAL 1 MONTH
GROUP BY user
What is the best way to achieve this with a single query?
Many thanks.
Just use a case statement to only count points when it meets your criteria.
SELECT
user,
SUM(points) AS points,
SUM(case
when date_achieved >= (CURRENT_DATE - INTERVAL 1 MONTH)
THEN points
else 0 END) points_last_Month
FROM myTable
GROUP BY user
select
user,
sum(points) as points_total,
sum(
case
when date_achieved >= current_date - interval 1 month then points
else 0
end
) as points_month
from myTable
group by user