How to get sum for different time period in one query - php

query 1:
SELECT SUM(duration) FROM table_name WHERE timestart >= past24hours
query 2:
SELECT SUM(duration) FROM table_name WHERE timestart >= past7days
Hi all, i want to combined above two query and get sum in query.
Any way to do this?
Currently i have 2 more query in addition to above for past 30 days and 365 days.
Anyone please help.

You can use union
like
SELECT SUM(duration) FROM table_name WHERE timestart >= past24hours
UNION
SELECT SUM(duration) FROM table_name WHERE timestart >= past7days

SELECT SUM(duration), 1 FROM table_name WHERE timestart >= '$date' - INTERVAL 1 DAY
UNION
SELECT SUM(duration), 2 FROM table_name WHERE timestart BETWEEN '$date' - INTERVAL 7 DAY AND '$date' - INTERVAL 1 DAY
this way you wont get rows with timestart in last 24 hours twice

One way is to get all sums with different alias is as
select
t.sum1,t.sum2
from(
select
sum(case when timestart >= past24hours then duration END) as sum1,
sum(case when timestart >= past7days then duration END) as sum2
from table_name
)t
You can add any number of sums within the query and give an alias name and add them in the select list so that they could be parsed later with your server side script.
With UNION it will return the same column/alias. When you have same sum value in UNION it will get only one and to get rid of it you can use UNION ALL

Related

how can i write as one query to get count in mysql

I want to get the today count of users and yesterday's users count for that i want to write only one query how can i do that..?
these are my queries I want only one query:
SELECT COUNT(*) FROM visitors group by visited_date ORDER by visited_date DESC limit 1,1 as todayCount
SELECT COUNT(*) FROM visitors group by visited_date ORDER by visited_date DESC limit 1,0 as yesterdayCount
My expected results or only 2 columns
todayCount yesterdayCount
2 4
This should do the trick:
SELECT COUNT(CASE
WHEN visited_date = CURDATE() THEN 1
END) AS todayCount ,
COUNT(CASE
WHEN visited_date = CURDATE() - INTERVAL 1 DAY THEN 1
END) AS yesterdayCount
FROM visitors
WHERE visited_date IN (CURDATE(), CURDATE() - INTERVAL 1 DAY)
GROUP BY visited_date
ORDER by visited_date
If you know the current and previous date, then you can do:
SELECT SUM(visited_date = CURDATE()) as today,
SUM(visited_date = CURDATE() - interval 1 day) as yesterday
FROM visitors
WHERE visited_date >= CURDATE() - interval 1 day;
If you don't know the two days, then you can do something similar, getting the latest date in the data:
SELECT SUM(v.visited_date = m.max_vd) as today,
SUM(v.visited_date < m.max_vd) as yesterday
FROM visitors v CROSS JOIN
(SELECT MAX(v2.visited_date) as max_vd FROM visitors v2) as m
WHERE v.visited_date >= m.max_vd - interval 1 day
Just try this simple query
select visited_date as date, COUNT(*) as count from `visitors`
group by `visited_date` order by `visited_date` asc
It will produce output as
It will work for you.
Try this:
$sqlToday = "Select COUNT(*) FROM menjava WHERE DATE(date_submitted)=CURRENT_DATE()";
$sqlYesterday = "Select COUNT(*) FROM menjava WHERE DATE(dc_created) = CURDATE() - INTERVAL 1 DAY";

Select rows from MYSQL table where dates between two columns containing weekend

I want to select rows from a MYSQL table where dates between two columns start_date, end_date containing weekends
I tried found this but it is not helpful
My table columns are Name start_date end_date amount
I want to print name and amount if days between start_date and end_date containing Saturday and Sunday.
Use DAYNAME function. It gives Dayname of a particular date.
Try this,
select * from yourtable where
(DAYNAME(start_date) = 'Saturday' or DAYNAME(start_date) = 'Sunday') and
(DAYNAME(end_date) = 'Saturday' or DAYNAME(end_date) = 'Sunday');
Hope it will help.
P.S. I din't run this query.
From what I understand, you want to take two columns as start and end dates and count the number of weekend days between them. Is that correct?
This answer How to get list of dates between two dates in mysql select query has some SQL for getting a list of all dates in a range.
To build on that you could use that query as an inner join, selecting only the dates you need based on your start and end columns. Then count Sundays and Saturdays using DAYNAME.
Here's an example that gets close to what you should use. This is not exactly what you should use! This is only built for hard coding the dates (and very close to passing them in as parameters). You should adapt it by joining your table to it!. I didn't write it that way because: I'm lazy and didn't want to make a table for testing and demonstrating it, and (more importantly) I wanted to help you and not just hand over a solution.
select count(one_date), dayname(one_date) week_day from
(select * from
(select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) one_date from
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v ) as all_days
where one_date between '2016-10-01' and '2016-11-15' -- <---- DON'T HARDCODE THESE, JOIN YOUR TABLE TO THE all_days AND FILTER THE DAYS YOU WANT THAT WAY
group by week_day
having week_day in ('Sunday', 'Saturday');
This is a lengthy query, may slowdown the performance. But this can give you desired output
SELECT x.id,x.name,x.amount FROM
(SELECT name,amount,DATEDIFF(end_date,start_date)+1 AS totDays,
start_date AS day1,ADDDATE(start_date,1) AS day2,
ADDDATE(start_date,2) AS day3,ADDDATE(start_date,3) AS day4,
ADDDATE(start_date,4) AS day5,ADDDATE(start_date,5) AS day6,
end_date FROM your_table)X
WHERE x.totDays>5 OR (WEEKDAY(x.day1)>4 AND x.day1<=x.end_date) OR
(WEEKDAY(x.day2)>4 AND x.day2<=x.end_date) OR
(WEEKDAY(x.day3)>4 AND x.day3<=x.end_date) OR
(WEEKDAY(x.day4)>4 AND x.day4<=x.end_date) OR
(WEEKDAY(x.day5)>4 AND x.day5<=x.end_date) OR
(WEEKDAY(x.day6)>4 AND x.day6<=x.end_date);
Or try this,
SELECT name,amount FROM your_table WHERE
(DATEDIFF(end_date,start_date)+1) >5 OR
(WEEKDAY(start_date)>4 AND start_date<=end_date) OR
(WEEKDAY(ADDDATE(start_date,1))>4 AND ADDDATE(start_date,1)<=end_date) OR
(WEEKDAY(ADDDATE(start_date,2))>4 AND ADDDATE(start_date,2)<=end_date) OR
(WEEKDAY(ADDDATE(start_date,3))>4 AND ADDDATE(start_date,3)<=end_date) OR
(WEEKDAY(ADDDATE(start_date,4))>4 AND ADDDATE(start_date,4)<=end_date) OR
(WEEKDAY(ADDDATE(start_date,5))>4 AND ADDDATE(start_date,5)<=end_date);
Notes:
If DATEDIFF between start_date and end_date is greater than 5, then there will be weekends.
ADDDATE with start_date up to 5 and compare that with end_dateand if WEEKDAY of the output is greater than 4, then there will be weekends.
If you want to select rows where between start and end date there is a whole weekend (Saturday and Sunday together) you may use this query:
select name, amount FROM your_table WHERE
datediff(end_date,start_date) > 6
or
(datediff(end_date,start_date)+weekday(start_date)>=6
and weekday(start_date)<>6);
Assuming start_date and end_date inclusive datediff(end_date,start_date) for the whole week is equal 6, so if there is more days than one week we can be sure there is a weekend between. When there is less days between we have to check if the number of days starting from the given start weekday will cover the weekend but we can be sure that it's not true if the start day is Sunday (starting from Sunday six days later is Saturday but these two weekend days are not one after another).
In case you want to select rows where between start and end date there is at least one weekday (Saturday or Sunday) you can use this query
select name, amount FROM your_table WHERE
datediff(end_date,start_date)+weekday(start_date)>=5;

MySQL select all days in date range even if no data is available for day

I have entries for each days as a punch in/out clock. I would like to display all days for the date givens week and show the days even if no data in found for that day.
Example:
Monday 2015-05-04
- 2015-05-04 10:30:00
- 2015-05-04 15:45:34
Tuesday 2015-05-05
- 2015-05-05 08:43:23
- 2015-05-05 17:18:13
Wednesday 2015-05-06
- 2015-05-06 09:03:12
Thursday 2015-05-07
0 Entries
Friday 2015-05-08
0 Entries
The DB schema looks like:
id | user_id | punch_time | punch_status
I would ideally like to be able to change the date given to MySQL to any timestamp and it would show the days and results for that week.
Thanks :D
NEW
Any ideas why this doesn't work to get days when no records are present?
SELECT * FROM punch_clock, calendar_table WHERE calendar_table.dt = DATE(punch_clock.punch_time) && calendar_table.week_num = $week && calendar_table.y = $year ORDER BY punch_clock.punch_time
Newer Query
SELECT * FROM punch_clock LEFT JOIN calendar_table ON calendar_table.dt = DATE(punch_clock.punch_time) WHERE calendar_table.week_num = 18 && calendar_table.y = 2015;
With MySQL, I usually use a calendar table for this purpose (containing all the dates until 2030 for example)
It allows to do many other things like this kind of queries, manage special days, etc..
You'll want to LEFT JOIN your table on it, I mean this calendar table have to be "left positioned"
Taking your last query, I'd do this:
SELECT *
FROM calendar AS cal
LEFT JOIN punch_clock AS puc
ON (cal.dt = DATE(puc.punch_time))
WHERE TRUE
AND cal.week_num = 18
AND cal.y = 2015
;
Didn't try, but this is the idea.
Have a try of this:
SELECT *
FROM
(
SELECT a.Date AS mydate
FROM (
SELECT date('2015-05-08') - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY AS Date
FROM (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS a
CROSS JOIN (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS b
CROSS JOIN (SELECT 0 AS a
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9) AS c
) a
WHERE a.Date BETWEEN '2015-05-04' AND '2015-05-08'
) dates
LEFT JOIN
(
SELECT *
FROM
table1
) data
ON DATE_FORMAT(dates.mydate, '%Y%m%d') = DATE_FORMAT(data.punch_time, '%Y%m%d')
SQL Fiddle: http://sqlfiddle.com/#!9/72ee3/15/0
This is a fast but not that ideal solution for your question. But I think it's just enough for use.
If you'd like to solve the problem "perfectly", I suggest you reading this article: http://www.brianshowalter.com/calendar_tables
Even while this is a really old question I did not like the idea of an extra calendar table and came up with this query, adjusted for the question.
SELECT pc.`id`, pc.`user_id`, pc.`punch_status`, dates.`date` FROM punch_clock pc RIGHT JOIN (SELECT week.`date` FROM (
SELECT CURDATE() AS `date`
UNION SELECT CURDATE() + INTERVAL 1 DAY
UNION SELECT CURDATE() + INTERVAL 2 DAY
UNION SELECT CURDATE() + INTERVAL 3 DAY
UNION SELECT CURDATE() + INTERVAL 4 DAY
UNION SELECT CURDATE() + INTERVAL 5 DAY
UNION SELECT CURDATE() + INTERVAL 6 DAY
UNION SELECT CURDATE() - INTERVAL 1 DAY
UNION SELECT CURDATE() - INTERVAL 2 DAY
UNION SELECT CURDATE() - INTERVAL 3 DAY
UNION SELECT CURDATE() - INTERVAL 4 DAY
UNION SELECT CURDATE() - INTERVAL 5 DAY
UNION SELECT CURDATE() - INTERVAL 6 DAY
) AS week
WHERE YEARWEEK(`date`, 0) = YEARWEEK(CURDATE(), 0)) AS dates ON dates.`date` = DATE(pc.`punch_time`) ORDER BY dates.`date`
Not exactly pretty, but it does the job without an extra table. This uses a week from Monday to Sunday, use YEARWEEK(xxx, 1) for Sunday to Monday week.

Joining two select queries on a results field

I'm trying to join a query results on a field, 'min' - which is the hour:min of the event. I have two different select queries in one and I'm trying UNION (which may not be right, just trying different things, I find MySQL documentation very difficult to read).
So I want
H:M and then the result of addCount and projectsNum - so for each hour/min I have the stats.
Where am I going wrong?
(
SELECT
DATE_FORMAT(`when`, '%H:%i') as `min`,
COUNT(`ipAddress`) AS `addCount`
FROM `metric` m
WHERE `when` BETWEEN DATE_SUB(NOW(), INTERVAL 3 HOUR) AND NOW()
GROUP BY DAY(`when`), HOUR(`when`), MINUTE(`when`)
)
UNION
(
SELECT
DATE_FORMAT(v.`created`, '%H:%i') as `min`,
COUNT(v.`projID`) as `projectsNum`
FROM `projects` v
WHERE v.`created` BETWEEN DATE_SUB(NOW(), INTERVAL 3 HOUR) AND NOW()
GROUP BY DAY(v.`created`), HOUR(v.`created`), MINUTE(v.`created`)
)
UNION just appends a set of results to another set of results.
You need to use your second query as a sub-query:
SELECT
DATE_FORMAT(`when`, '%H:%i') as `min`,
COUNT(`ipAddress`) AS `addCount`,
projects_subquery.`projectsNum`
FROM `metric` m
JOIN (
SELECT
DATE_FORMAT(v.`created`, '%H:%i') as `min`,
COUNT(v.`projID`) as `projectsNum`
FROM `projects` v
WHERE v.`created` BETWEEN DATE_SUB(NOW(), INTERVAL 3 HOUR) AND NOW()
GROUP BY DAY(v.`created`), HOUR(v.`created`), MINUTE(v.`created`)
) AS projects_subquery ON projects_subquery.`min` = m.`min`
WHERE `when` BETWEEN DATE_SUB(NOW(), INTERVAL 3 HOUR) AND NOW()
GROUP BY DAY(`when`), HOUR(`when`), MINUTE(`when`)
This query probably performs terribly. I just brute-force copy-pasted from your original query to make it syntactically correct, but there must be a way to optimize it.

SQL time period query

I need to select from a table all rows that have date_added between CURDATE() and 6 weeks ago.
Help please.
SELECT *
FROM mytable
WHERE date_added BETWEEN CURDATE() - INTERVAL 6 WEEK AND CURDATE()
SELECT *
FROM a_table
WHERE date_added BETWEEN DATE_SUB(CURDATE(), INTERVAL 6 WEEK) AND CURDATE()
SELECT * FROM table_name WHERE TO_DAYS(NOW()) - TO_DAYS(date_added) <= 42
SELECT * FROM table_name WHERE DATEDIFF(NOW(),date_added)<=42
if you use dates in one year
select date_format(date, '%u') from tab
where (date_format(date, '%u')-date_format(now(), '%u'))>6
if you use dates with different years
you don't have to use dates with another year.
you can use
select
date_format(date, '%u') from tab
where (date_format(date, '%u')-date_format(now(), '%u'))>6
and
date_format(date, '%u') from tab
where (date_format(date, '%Y')-date_format(now(), '%Y'))=0
you can optimize query with join if you want. I think you know how to do it

Categories