I am having 3 tables, containing some records which have a date and a numeric value (the tables can't be merged). I want to make up a bar chart using the information from the tables. The bar chart is grouped by days and should display the last seven days.
Earlier i had two tables and used the following query-scheme:
SELECT
t.credits1,
t.credits2,
t.date
FROM
(
(
SELECT
t1.credits1,
t2.credits2,
t1.date
FROM
(
SELECT
SUM(credits) AS credits1,
date
FROM
table1
WHERE
table1.date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY
DATE(table1.date)
) t1
LEFT JOIN
(
SELECT
SUM(credits) AS credits2,
date
FROM
table2
WHERE
table2.date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY
DATE(table2.date)
) t2
ON t1.date = t2.date
)
UNION
(
SELECT
t1.credits1,
t2.credits2,
t1.date
FROM
(
SELECT
SUM(credits) AS credits1,
date
FROM
table1
WHERE
table1.date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY
DATE(table1.date)
) t1
RIGHT JOIN
(
SELECT
SUM(credits) AS credits2,
date
FROM
table2
WHERE
table2.date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY
DATE(table2.date)
) t2
ON t1.date = t2.date
)
) t GROUP BY
DATE(date)
(pseudo code)
But how can i do this with more than 2 tables?
Is there any chance to set the dates of the past 7 days as a base, so that i get 7 records everytime?
To point out the problem: If I dont have records in the first table for a day, i won't get the records from the other tables for that day.
I assume the 3 tables have similar schemas? Try using UNION ALL to join the tables together.
SELECT ABB1.date, SUM(ABB1.credit) AS daily_total
FROM
(SELECT date, credits
FROM table1
UNION ALL
SELECT date, credits
FROM table1
UNION ALL
SELECT date, credits
FROM table2) AS ABB1
WHERE DATE >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
Related
this is my table
I wish to query the customer that didn't have any record within 30days
I try this query
SELECT *,DATE_FORMAT(date, '%m/%d/%Y')
FROM transaction
WHERE date <= DATE_SUB(SYSDATE(), INTERVAL 30 DAY)
AND type = 'deposit'
ORDER BY trans_id DESC
but it will return all the data older than 30 days,
my aim is to get the user who have no new record within 30 days, so it should only show testuser2
how can I make it?
You could try using a left join on the customer with transcation <= 30 anche check for not matching values
SELECT t1.*,DATE_FORMAT(t1.date, '%m/%d/%Y')
FROM transaction t1
LEFT JOIN (
SELECT customer FROM transaction
WHERE date <= DATE_SUB(SYSDATE(), INTERVAL 30 DAY)
) t2 ON t2customer = t1.customer
WHERE t1.date <= DATE_SUB(SYSDATE(), INTERVAL 30 DAY)
AND t1.type = 'deposit'
AND t2.customer IS NULL
ORDER BY trans_id DESC
This question already has answers here:
SQL Server: How to select all days in a date range even if no data exists for some days
(12 answers)
Closed 4 years ago.
In db i have comments table and for statistics i would like to get total comments count per day (last 7 days).
I use:
select date(created_at) as day, count(*) as total_comments
from comments
where DATEDIFF(NOW(), created_at) <= 7
group by day
but when there are not comments in particular day it wont return anything. How can i fill missing days?
You need a table for all the 7 days
select t1.day, t2. total_comments
from (
select 1 day from dual
union
select 2 from dual
union
select 3 from dual
union
select 4 from dual
union
select 5 from dual
union
select 6 from dual
union
select 7 from dual
) t1
left join (
select date(created_at) as day
, count(*) as total_comments
from comments where DATEDIFF(NOW(), created_at) <= 7
group by day
) t2 on t1.day = t2.day
You can use a different strategy, without the need for different tables:
select
(NOW() - INTERVAL 1 DAY) as day, (SELECT count(*) as total_comment from comments where date(created_at) = day ) as total_comments
UNION
select (NOW() - INTERVAL 2 DAY) as day, (SELECT count(*) as total_comment from comments where date(created_at) = day ) as total_comments
UNION
select (NOW() - INTERVAL 3 DAY) as day, (SELECT count(*) as total_comment from comments where date(created_at) = day ) as total_comments
UNION
select (NOW() - INTERVAL 4 DAY) as day, (SELECT count(*) as total_comment from comments where date(created_at) = day ) as total_comments
UNION
select (NOW() - INTERVAL 5 DAY) as day, (SELECT count(*) as total_comment from comments where date(created_at) = day ) as total_comments
UNION
select (NOW() - INTERVAL 6 DAY) as day, (SELECT count(*) as total_comment from comments where date(created_at) = day ) as total_comments
UNION
select (NOW() - INTERVAL 7 DAY) as day, (SELECT count(*) as total_comment from comments where date(created_at) = day ) as total_comments
I have a table
id, date
a , 2017-01-01
a , 2017-01-02
b , 2017-02-03
...
and I'd like to compute for each day D, how many distinct user appeared exactly 7 days ago (on that day), but not in-between D-7 and D. Don't care about if they appear before day D
And the output shall be
date, count
2017-01-01, 23
2017-01-02, 33
etc
I've been thinking about this for quite a while, but can't figure out the D to D+7 part out. Easily converted into python, but I'd like to sharpen my SQL skills :)
I know basic select, group by clauses, but I'm just wondering if there're any advanced techniques I should know about.
Any help would be appreciated
You can check if the user appeared on that day and 7 days ago
SELECT DDate,
COUNT(*) cnt
FROM tablename a
WHERE id IN (SELECT id
FROM tablename
WHERE DDate = DATE_SUB(a.DDate, INTERVAL 7 DAY)
)
GROUP BY DDate
I'm just trying to help you with the assumption of what I understand about your question
just from the documentation
select count(date), date from tablename where date<=CURDATE() + interval 7 day group by date
You can use a left join on the same table for the 7 days in the future to see if the ID shows up. If it doesn't show up, the left joined table's id will be null.
select count(distinct t1.id), t1.date + interval 7 day
from table t1
left join table t2 on t2.id = t1.id and t2.date < t1.date + interval 7 day and t2.date >= t1.date
where t2.id is null;
Similar to Ferdinand Gasper's answer, but this excludes the users who appeared less than 7 days before:
SELECT date, COUNT(DISTINCT id)
FROM yourTable AS t1
WHERE id IN (SELECT id
FROM yourTable AS t2
WHERE t2.date = DATE_SUB(t1.date, INTERVAL 7 DAY))
AND id NOT IN (SELECT id
FROM yourTable AS t2
WHERE t2.date BETWEEN DATE_SUB(t1.date, INTERVAL 6 DAY) AND DATE_SUB(t1.date, INTERVAL 1 DAY))
GROUP BY date
Personal leave is 10 days. I need the remaining leave to be subtracted from the total personal leave i.e 10 days
result i have
SELECT id, firstname,lastname,join_date, completion_date,title, leave_from,leave_to, Given_leave_Days,Taken_Leave_Days,Remaining_Leave_Days FROM (SELECT T1.id,T1.firstname,T1.lastname,T1.join_date,T1.completion_date,T0.title,T2.leave_from,T2.leave_to,T2.user_id,T0.Leave_Days as Given_leave_Days,SUM(DATEDIFF(T2.leave_to,T2.leave_from)+1) AS Taken_Leave_Days ,T0.Leave_Days - SUM(DATEDIFF(T2.leave_to,T2.leave_from)+1) as 'Remaining_Leave_Days' FROM users_leave_request T2 INNER JOIN users T1 ON T2.user_id = T1.id INNER JOIN leave_type T0 ON T2.leave_type_id = T0.id GROUP BY T1.id, T1.firstname, T1.lastname, T1.join_date,T1.completion_date,T0.title,T2.leave_from,T2.leave_to,Given_leave_Days order by firstname) A
i have to display the result in frontend.
result in frontend
The general answer is
select date_sub(now(), interval 10 day)
You can replace now() for any date from a table, you can change day for month, year, etc.
The result from my example is a date 10 days before today. For example, if you want to filter only the dates older than 10 days you would do like this:
select * from mytable t where t.mydate < date_sub(now(), interval 10 day)
I have two tables "temp_user_batches" and "user_activities" i am trying to find sum of user_activities for users present in temp_user_batches table.
problem is sum of user_activities is getting multiplied by number of times in ratio of occurences of user in temp_user_batches table.
Below is temp_user_batches table
This is user_activities table
it is supposed to give sum of time_spent column 649 + 364 = 1013 but instead its giving 2016
my query is:
SELECT temp_user_batches.user_id as user_id,
temp_user_batches.activity_goal as goal,
DATE_SUB(CURDATE(), INTERVAL 7 day) as min_activity_date,
CURDATE() as max_activity_date,
(sum(user_activities.time_spent)/60) as total_time_spent
FROM temp_user_batches
INNER JOIN user_activities
ON temp_user_batches.user_id = user_activities.user_id
WHERE activity_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 day) AND CURDATE()
group by user_id, goal, max_activity_date, min_activity_date
You can use a derived table that contains the DISTINCT pairs of user_id, activity_goal from table temp_user_batches:
SELECT t1.user_id as user_id,
t2.activity_goal as goal,
DATE_SUB(CURDATE(), INTERVAL 7 day) as min_activity_date,
CURDATE() as max_activity_date,
(sum(t2.time_spent)/60) as total_time_spent
FROM (
SELECT DISTINCT user_id, activity_goal
FROM temp_user_batches) AS t1
INNER JOIN user_activities AS t2 ON t1.user_id = t2.user_id
WHERE activity_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 day) AND CURDATE()
group by user_id, goal, max_activity_date, min_activity_date
From my understanding, you should try to GROUP_BY the temp_user_batches on user_id, last_activity before joining it with user_activities. This is because now you join user_activities on 2 rows instead of 1 row the way you want (from what I understand).
Something like:
SELECT
temp_user_batches.user_id AS user_id,
temp_user_batches.activity_goal AS goal,
DATE_SUB(CURDATE(), INTERVAL 7 DAY) AS min_activity_date,
CURDATE() AS max_activity_date,
(SUM(user_activities.time_spent) / 60) AS total_time_spent
FROM
(SELECT
*
FROM
temp_user_batches
GROUP BY user_id , last_activity)
INNER JOIN
user_activities ON temp_user_batches.user_id = user_activities.user_id
WHERE
activity_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE()
GROUP BY user_id , goal , max_activity_date , min_activity_date