MYSQL how to count how many hours where data exists - mysql

I am trying to count how many hours of the day there is data in the database.
I use this query:
SELECT
HOUR(date) AS `hour`, COUNT(date)
FROM fb_posts
WHERE DATE(date) = CURDATE() - INTERVAL 1 DAY
GROUP BY hour
I got the query from here
example:
hour COUNT(date)
00 55
01 2
02 33
Now I want calculate how many hours there was data?
Above example should output value 3, because there was data at hour 00, 01 and 02
something would like to add COUNT(hour)like this:
SELECT
HOUR(date) AS `hour`, COUNT(date)**,COUNT(hour)**
FROM fb_posts
WHERE DATE(date) = CURDATE() - INTERVAL 1 DAY
GROUP BY hour

select count(*)
from
(
SELECT HOUR(date) AS hour
FROM fb_posts
WHERE DATE(date) = CURDATE() - INTERVAL 1 DAY
GROUP BY hour
) tmp

you are looking for count(distinct column) https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_count-distinct
SELECT count(distinct HOUR(date)) AS distinct_hour_count
FROM fb_posts
WHERE DATE(date) = CURDATE() - INTERVAL 1 DAY

Related

How to count only business days (Monday to Friday) per month between two dates in MySQL 5.7?

I have the following table called vacations, where the employee id is displayed along with the start and end date of their vacations:
employee
start
end
1001
26/10/21
22/11/21
What I am looking for is to visualize the number of vacation days that each employee had, but separating them by month and without non-working days (Saturdays and Sundays).
For example, if you wanted to view the vacations for employee 1001, the following result should be displayed:
days
month
4
10
16
11
I have the following query that I have worked with:
SELECT id_employee,
EXTRACT(YEAR_MONTH FROM t.Date) as YearMonth,
COUNT(1) as Days
FROM (SELECT v.id_employee,
DATE_ADD(v.start, interval s.seq - 1 DAY) AS Date
FROM vacations v
CROSS JOIN seq_1_to_100 s
WHERE DATE_ADD(v.start, interval s.seq - 1 DAY) <= v.end
ORDER BY v.id_employee, , v.start, s.seq
) t
GROUP BY id_employee,
EXTRACT(YEAR_MONTH FROM t.Date)
With this query I separate the days between a range of two dates with their respective month, but how could I adapt it to stop considering Saturdays and Sundays? I'm working with MySQL 5.7 in phpMyAdmin
instead of count sum the compaarison of weekday function, which give what day it is .
But you should always save fates n a valid mysql manner 2021-10-28
SELECT id_employee,
EXTRACT(YEAR_MONTH FROM t.Date) as YearMonth,
SUM(WEEKDAY(`Date`) < 5) as Days
FROM (SELECT v.id_employee,
DATE_ADD(v.start, interval s.seq - 1 DAY) AS Date
FROM vacations v
CROSS JOIN seq_1_to_100 s
WHERE DATE_ADD(v.start, interval s.seq - 1 DAY) <= v.end
ORDER BY v.id_employee, v.start, s.seq
) t
GROUP BY id_employee,
EXTRACT(YEAR_MONTH FROM t.Date)

Get name of last two months in SQL

I have a query that compares this month's numbers to last month and upper month. The only issue is that colleagues complain about the labelling.
I have used M1 = last month and M2 = upper month, but some people still get it mixed up. I want to put in the actual month instead of M1, M2 and so on. Any ideas would help. This is my code
SELECT *,
CONCAT(FORMAT((current_downloads/M_1)*100,2),'%') AS `M_1_Ratio`,
CONCAT(FORMAT((current_downloads/M_2)*100,2),'%') AS `M_2_Ratio`
FROM
(SELECT count(*) AS current_downloads
FROM `purchase`
WHERE date(`purchase`.`timestamp`) >= DATE_FORMAT(NOW() ,'%Y-%m-01')) t1
JOIN
(SELECT count(*) AS M_1
FROM `purchase`
WHERE date(`purchase`.`timestamp`) BETWEEN DATE_SUB(DATE_FORMAT(NOW(),'%Y-%m-01'), INTERVAL 1 MONTH) AND DATE_SUB(DATE(NOW()), INTERVAL 1 MONTH)) t2
JOIN
(SELECT count(*) AS M_2
FROM `purchase`
WHERE date(`purchase`.`timestamp`) BETWEEN DATE_SUB(DATE_FORMAT(NOW(),'%Y-%m-01'), INTERVAL 2 MONTH) AND DATE_SUB(DATE(NOW()), INTERVAL 2 MONTH)) t3
That gives something like this.
I need the header names to be actual months.
This is a horrible hack (and will only work if your output is purely for presentation), but you could just add another line of data to the table which includes the month names by using a UNION:
SELECT DATE_FORMAT(NOW(), '%b %y') as Current_Downloads, DATE_FORMAT(NOW() - INTERVAL 1 MONTH, '%b %y') as M_1, DATE_FORMAT(NOW() - INTERVAL 2 MONTH, '%b %y') as M_2, DATE_FORMAT(NOW() - INTERVAL 1 MONTH, '%b %y') as M_1_Ratio, DATE_FORMAT(NOW() - INTERVAL 2 MONTH, '%b %y') as M_2_Ratio
UNION ALL
... your query ...
This will give you something that looks like this:
Current Downloads M_1 M_2 M_1_Ratio M_2_Ratio
Mar 18 Feb 18 Jan 18 Feb 18 Jan 18
12,168 12,121 13,345 100.39% 91.18%

How to get unique values for several different time ranges WHERE exec_datetime >= NOW() - INTERVAL n DAY?

I can select the total amount of unique ip addresses between a single time range
SELECT COUNT(DISTINCT ip_address) as ip_addr, exec_datetime
FROM requests
WHERE exec_datetime >= NOW() - INTERVAL 1 DAY;
ip_addr exec_datetime
45 12/10/2012 5:21
How do I return a result set for the following clauses in a single query...
WHERE exec_datetime >= NOW() - INTERVAL 1 DAY;
WHERE exec_datetime >= NOW() - INTERVAL 2 DAY;
...
WHERE exec_datetime >= NOW() - INTERVAL 14 DAY;
...so that the result set would look like this?
ip_addr exec_datetime
45 11/26/2012 5:21
85 11/27/2012 5:21
130 11/28/2012 5:21
170 11/29/2012 5:21
... ...
I would use something like this:
SELECT
COUNT(DISTINCT requests.ip_address) ip_addr,
days.day
FROM
(SELECT now()-INTERVAL 1 DAY as day UNION
SELECT now()-INTERVAL 2 DAY UNION
...
SELECT now()-INTERVAL 14 DAY) days
INNER JOIN requests
on requests.exec_datetime >= days.day
GROUP BY
days.day

SQL Hourly Data

The query below retrieves weather data from a MySql database, and groups this data in to an hourly format.
select hour(datetime) AS hour
, avg(Temperature) as AVGT
from Database.minute
WHERE DATETIME
BETWEEN (CURDATE() + INTERVAL (SELECT hour(NOW())) hour - INTERVAL 23 hour)
AND ((CURDATE() + INTERVAL (SELECT hour(NOW())) hour))
group by hour
order by (CURDATE() + INTERVAL (SELECT hour(NOW())) hour - INTERVAL 23 hour)
Output is as follows:
hour AVGT
19 11.730
20 11.970
21 11.970
22 11.760
23 11.660
0 11.700
1 11.830
2 12.370
3 12.770
4 12.840
5 12.840
6 12.540
7 12.500
8 12.030
9 12.100
10 12.300
11 12.060
12 11.090
13 10.920
14 10.920
15 10.820
16 10.760
17 10.690
18 10.560
The time is now 18:15. All of the above output is correct apart from the data gathered for hour '18'. Instead of getting the average value between 18:00 and 18:15, it just outputs the average at time 18:00. ie. ignoring data between 18:01 and 18:14.
How can I modify the above query to include data in the current hour (18:00 to Now)?
Thanks
Why don't you simply try
SELECT Hour(datetime) AS hour,
Avg(temperature) AS AVGT
FROM DATABASE.minute
WHERE datetime BETWEEN ( Curdate() + INTERVAL (SELECT Hour(Now())) hour -
INTERVAL 23 hour ) AND Now()
GROUP BY hour
ORDER BY ( Curdate() + INTERVAL (SELECT Hour(Now())) hour - INTERVAL 23 hour )
I agree with #Ankur's answer (your filter citerion should not filter records up to the current hour, but rather the current time), however your date/time operations are very strange:
You don't need a subquery (SELECT Hour(NOW())) to obtain HOUR(NOW());
You can express ( Curdate() + INTERVAL (SELECT Hour(NOW())) hour - INTERVAL 23 hour ) more simply:
CURDATE() + INTERVAL HOUR(NOW()) - 23 HOUR
Or, in my view, more clearly:
DATE_FORMAT(NOW() - INTERVAL 23 HOUR, '%Y-%m-%d %H:00:00')
Your ORDER BY clause is a constant and therefore achieves nothing: did you mean to order by hour?
Therefore:
SELECT HOUR(datetime) AS hour,
AVG(Temperature) AS AVGT
FROM Database.minute
WHERE datetime BETWEEN
DATE_FORMAT(NOW() - INTERVAL 23 HOUR, '%Y-%m-%d %H:00:00')
AND NOW()
GROUP BY hour
ORDER BY hour

group by day for the past 5 days

I am trying to select the sum of an integer field for the past 5 days, and I need to group it for each day.
I'm having a bit of issues figuring out the grouping. Here's my sql query so far:
select
sum(`amount_sale`) as total
from `sales`
where the_date >= unix_timestamp((CURDATE() - INTERVAL 5 DAY))
that works fine for generating the sum for all 5 days together, but I need to break this down so that it shows the sum for each of the past 5 days i.e:
day 1 - $200
day 2- $500
day 3 - $20
etc.
SELECT DATE(FROM_UNIXTIME(the_date)) AS dt, SUM(amount_sale) AS total
FROM sales
WHERE the_date >= UNIX_TIMESTAMP((CURDATE() - INTERVAL 5 DAY))
GROUP BY
dt
To returns 0 for missing dates:
SELECT dt, COALESCE(SUM(amount_sale), 0) AS total
FROM (
SELECT CURDATE() - INTERVAL 1 DAY AS dt
UNION ALL
SELECT CURDATE() - INTERVAL 2 DAY AS dt
UNION ALL
SELECT CURDATE() - INTERVAL 3 DAY AS dt
UNION ALL
SELECT CURDATE() - INTERVAL 4 DAY AS dt
UNION ALL
SELECT CURDATE() - INTERVAL 5 DAY AS dt
) d
LEFT JOIN
sales
ON the_date >= UNIX_TIMESTAMP(dt)
AND the_date < UNIX_TIMESTAMP(dt + INTERVAL 1 DAY)
GROUP BY
dt
This is not a very elegant solution, however, MySQL lacks a way to generate recordsets from scratch.
use the format function to return weekday nr: SELECT DATE_FORMAT(the_date, '%w');
use between
like select * from XXX where date between date(...) and date(...) group by date Limit 0,5
should do it