I have a table in which the value are
Table_hello
date col2
2012-01-31 23:01:01 a
2012-06-2 12:01:01 b
2012-06-3 20:01:01 c
Now i want to select date
in days if it is 3 days before or less
in hours if it is 24 hours before or less
in minutes if it is 60 minutes before or less
in seconds if it is 60 seconds before or less
in simple format if it is before 3days or more
OUTPUT
for row1 2012-01-31 23:01:01
for row2 1 day ago
for row3 1 hour ago
UPDATE
My sql query
select case
when TIMESTAMPDIFF(SECOND, `date`,current_timestamp) <= 60
then concat(TIMESTAMPDIFF(SECOND, `date`,current_timestamp), ' seconds')
when TIMESTAMPDIFF(DAY, `date`,current_timestamp) <= 3
then concat(TIMESTAMPDIFF(DAY, `date`,current_timestamp), ' days')end
when TIMESTAMPDIFF(HOUR, `date`,current_timestamp) <= 60
then concat(TIMESTAMPDIFF(HOUR, `date`,current_timestamp), ' hours')
when TIMESTAMPDIFF(MINUTE, `date`,current_timestamp) <= 60
then concat(TIMESTAMPDIFF(MINUTE, `date`,current_timestamp), ' minutes')
from table_hello
Only problem is i am unable to use break and default in sql like switch case in c++
Use the timestampdiff function for that and CASE:
select case
when TIMESTAMPDIFF(SECOND, `date`,current_timestamp) <= 60
then concat(TIMESTAMPDIFF(SECOND, `date`,current_timestamp), ' seconds')
when TIMESTAMPDIFF(DAY, `date`,current_timestamp) <= 3
and TIMESTAMPDIFF(DAY, `date`,current_timestamp) >= 1
...
end as time_diff
from Table_hello
where TIMESTAMPDIFF(DAY, `time`,current_timestamp) >= 3
Related
Help create a query that will select records from the table for the past period from 6AM until 6AM, the table has a timestamp field.
I will explain, for example:
Now: 2019-06-15 04:44:42
Period: 2019-06-13 06:00:00 - 2019-06-14 06:00:00
Now: 2019-06-15 07:44:42
Period: 2019-06-14 06:00:00 - 2019-06-15 06:00:00
Now: 2019-06-16 01:44:42
Period: 2019-06-14 06:00:00 - 2019-06-15 06:00:00
I think I was not the easiest request:
SELECT * FROM `table` WHERE `timestamp`
BETWEEN
DATE_ADD(DATE(NOW() - INTERVAL '1 6' DAY_HOUR), INTERVAL 6 HOUR)
AND
DATE_ADD(DATE(NOW() - INTERVAL '0 6' DAY_HOUR), INTERVAL 6 HOUR);
How simpler?
You can get the upper range limit with:
date(now() - INTERVAL 6 HOUR) + INTERVAL 6 HOUR
The lower limit would be exactly one day (24 hours) earlier:
date(now() - INTERVAL 6 HOUR) + INTERVAL 6 HOUR - INTERVAL 1 day
So your query could be:
SELECT *
FROM `table` t
WHERE t.timestamp >= date(now() - INTERVAL 6 HOUR) + INTERVAL 6 HOUR - INTERVAL 1 day
AND t.timestamp < date(now() - INTERVAL 6 HOUR) + INTERVAL 6 HOUR
But to avoid code duplication I would rewrite it to:
SELECT t.*
FROM `table` t
CROSS JOIN (
SELECT date(now() - INTERVAL 6 HOUR) + INTERVAL 6 HOUR as upper_limit
) r -- r for "range"
WHERE t.timestamp >= r.upper_limit - INTERVAL 1 day
AND t.timestamp < r.upper_limit
You can though use <= r.upper_limit instead of < r.upper_limit to get the same result as with BETWEEN.
SELECT start, start +interval 24 hour end
FROM ( SELECT date(now())
- interval if(hour(now())>6, 1, 2) day
+ interval 6 hour
as start
) dates;
I have a table with the following data:
I am looking to group the rows into the following:
Within the last day (everything within the last 24 hours)
Within the last 7 days (everything within the last week)
Within the last 30 days (everything within the last month)
The end result for the above rows would look something like:
I can group the records into these brackets right now with:
SELECT (CASE WHEN created_at = CURDATE() THEN '1 Day'
WHEN created_at >= CURDATE() - INTERVAL 6 DAY THEN '7 Days'
WHEN created_at >= CURDATE() - INTERVAL 29 DAY THEN '30 Days'
END) AS Timeframe, COUNT(*) AS Count
FROM my_table
GROUP BY (CASE WHEN created_at = CURDATE() THEN '1 Day'
WHEN created_at >= CURDATE() - INTERVAL 6 DAY THEN '7 Days'
WHEN created_at >= CURDATE() - INTERVAL 29 DAY THEN'30 Days'
END)
But this will prevent individual records from being counted more than once. For example, lines 2 and 3 in the first picture needs to be counted in all three brackets (1 day, 7 days, and 30 days) - while lines 6 through 9 only needs to be counted in the 30 days bracket.
How would you do this with MySQL?
It is easiest to do this as columns, rather than rows:
SELECT SUM(created_at = CURDATE()) as today
SUM(created_at >= CURDATE() - INTERVAL 6 DAY) as last_7_days,
SUM(created_at >= CURDATE() - INTERVAL 29 DAY) as last_30_days,
SUM(created_at < CURDATE() - INTERVAL 29 DAY) as older
FROM my_table;
If you want your response in several rows, instead of just one with several columns, take #Gordon Linoff as your starting point... but perform the queries "one row at at time" (it won't be as efficient, because you visit the table 4 times instead of 1!):
-- Row for the 1 day timeframe
SELECT '1 Day' AS `Timeframe`, SUM(created_at = CURDATE()) AS `Count`
FROM my_table
UNION
-- Row for the 7 days timeframe...
SELECT '7 Days' AS `Timeframe`, SUM(created_at >= CURDATE() - INTERVAL 6 DAY) AS `Count`
FROM my_table
UNION
SELECT '30 Days' AS `Timeframe`, SUM(created_at >= CURDATE() - INTERVAL 29 DAY) AS `Count`
FROM my_table
UNION
SELECT 'Older' AS `Timeframe`, SUM(created_at < CURDATE() - INTERVAL 29 DAY) AS `Count`
FROM my_table ;
If you can use MariaDB instead of MySQL, you can use a WITH, which will allow the query to be efficient again:
WITH stats AS
(
SELECT SUM(created_at = CURDATE()) as today,
SUM(created_at >= CURDATE() - INTERVAL 6 DAY) as last_7_days,
SUM(created_at >= CURDATE() - INTERVAL 29 DAY) as last_30_days,
SUM(created_at < CURDATE() - INTERVAL 29 DAY) as older
FROM my_table
)
-- Convert to rows with negligible overhead
SELECT '1 Day' AS `Timeframe`, today FROM stats
UNION
SELECT '7 Days', last_7_days FROM stats
UNION
SELECT '30 Days', last_30_days FROM stats
UNION
SELECT 'Older', older FROM stats ;
In both cases, you'll get (as of 2017-07-25):
Timeframe | today
:-------- | ----:
1 Day | 0
7 Days | 4
30 Days | 8
Older | 0
dbfiddle here
SELECT '2017-05-30' AS `short_date`,
'Stats' AS `group`,
'Active ' AS `subgroup`,
'' AS `row`,
CASE
WHEN COUNT(DISTINCT(guild_name)) >= 1 AND COUNT(DISTINCT(guild_name)) <= 5 THEN '1 - 5 '
WHEN COUNT(DISTINCT(guild_name)) >= 6 AND COUNT(DISTINCT(guild_name)) <= 10 THEN '6 - 10 '
WHEN COUNT(DISTINCT(guild_name)) >= 11 AND COUNT(DISTINCT(guild_name)) <= 15 THEN '11 - 15 '
WHEN COUNT(DISTINCT(guild_name)) >= 16 AND COUNT(DISTINCT(guild_name)) <= 20 THEN '16 - 20 '
WHEN COUNT(DISTINCT(guild_name)) >= 21 AND COUNT(DISTINCT(guild_name)) <= 25 THEN '21 - 25 '
WHEN COUNT(DISTINCT(guild_name)) >= 30 THEN '> 30' END AS `value`
FROM table
WHERE guild_name !=0
GROUP BY
`short_date`,
`group`,
`subgroup`
How not to count a value in each case, how to count it once and use in each case?
How about you move the count to a subquery and move the case outside like this:
select `short_date`, `group`, `subgroup`, `row`,
CASE
WHEN nb_guild >= 1 AND nb_guild <= 5 THEN '1 - 5 '
WHEN nb_guild >= 6 AND nb_guild <= 10 THEN '6 - 10 '
WHEN nb_guild >= 11 AND nb_guild <= 15 THEN '11 - 15 '
WHEN nb_guild >= 16 AND nb_guild <= 20 THEN '16 - 20 '
WHEN nb_guild >= 21 AND nb_guild <= 25 THEN '21 - 25 '
WHEN nb_guild >= 30 THEN '> 30'
END AS `value`
from
(
SELECT '2017-05-30' AS `short_date`,
'Stats' AS `group`,
'Active ' AS `subgroup`,
'' AS `row`,
COUNT(DISTINCT(guild_name)) as nb_guild
FROM table
WHERE guild_name !=0
GROUP BY
`short_date`,
`group`,
`subgroup`
) as subquery
This way your count only gets executed once in the subquery and your outer query does its treatment on the resulting resultset.
So in my database I have 2 dates I want to get the difference between. They are in the format 2013-07-31 00:00:00. I want the different in weeks, not time. So say date 1 - date 2 = 3 days and 12 hours. I want this to be represented as a week, as in 0.5 weeks. How can I do this in my sql query?
NOTE: I want the value returned to be a decimal, e.g. 1.5 not a string
This will provide you a whole number:
SELECT TIMESTAMPDIFF(WEEK, date1, date2) AS weeks;
To include a fraction for days, use:
SELECT TIMESTAMPDIFF(DAY, date1, date2) / 7 AS weeks_days;
or a fraction for seconds, use:
SELECT TIMESTAMPDIFF(SECOND, date1, date2) / 604800 AS weeks_secs;
as 604800 is 7 * 24 * 60 * 60;
Here's an example:
SET #date1 = NOW() - INTERVAL 777 HOUR, #date2 = NOW();
SELECT
TIMESTAMPDIFF(WEEK, #date1, #date2) AS weeks,
TIMESTAMPDIFF(DAY, #date1, #date2) / 7 AS weeks_days,
TIMESTAMPDIFF(SECOND, #date1, #date2) / 604800 AS weeks_secs;
returns:
+-------+------------+------------+
| weeks | weeks_days | weeks_secs |
+-------+------------+------------+
| 4 | 4.5714 | 4.6250 |
+-------+------------+------------+
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