Bigquery Table Lead Column Values Based On Date - mysql

I want to duplicate a (revenue) column and shift it one year in order to make YoY comparisons. Currently looking to lead values in a Big Query table based on a specific date to achieve this but stuck.
I used DATE_ADD to create a new column to get the date of last year but now I want to get a column next to it with the revenue based on the DATE_ADD date.
One problem is that not all locations include the same date, that's why it's harder to make the shift.
There is no way to properly format a table so I have an image of the intended result here. Where basically the revenue_last_year should fill in with the value of the revenue column corresponding to the date_add column and the right location.
The query below is as far as I've been able to go:
SELECT
Date,
location,
revenue,
DATE_ADD(date, INTERVAL -1 YEAR) AS DateAdd,
LEAD(revenue, ##OFFSET## ) OVER (PARTITION BY location ORDER BY date DESC) AS revenue_last_year
FROM
`dataset.table1`
Does anyone have a suggestion on how to relate the offset value to the right date? Or should I approach this in a completely different way?

Below is for BigQuery Standard SQL
#standardSQL
SELECT
a.date, a.location, a.revenue,
DATE_SUB(a.date, INTERVAL 1 YEAR) date_last_year,
IFNULL(b.revenue, 0) revenue_last_year
FROM `project.dataset.table` a
LEFT JOIN `project.dataset.table` b
ON a.location = b.location
AND DATE_SUB(a.date, INTERVAL 1 YEAR) = b.date
You can test, play with above using dummy data as in below example
#standardSQL
WITH `project.dataset.table` AS (
SELECT DATE '2018-02-20' `date`, 'A' location, 1 revenue UNION ALL
SELECT '2018-02-20', 'B', 2 UNION ALL
SELECT '2018-02-21', 'A', 3 UNION ALL
SELECT '2018-02-22', 'B', 4 UNION ALL
SELECT '2019-02-20', 'A', 5 UNION ALL
SELECT '2019-02-20', 'B', 6 UNION ALL
SELECT '2019-02-21', 'A', 7 UNION ALL
SELECT '2019-02-21', 'B', 8 UNION ALL
SELECT '2019-02-22', 'A', 9 UNION ALL
SELECT '2019-02-22', 'B', 10
)
SELECT
a.date, a.location, a.revenue,
DATE_SUB(a.date, INTERVAL 1 YEAR) date_last_year,
IFNULL(b.revenue, 0) revenue_last_year
FROM `project.dataset.table` a
LEFT JOIN `project.dataset.table` b
ON a.location = b.location
AND DATE_SUB(a.date, INTERVAL 1 YEAR) = b.date
-- ORDER BY a.date, a.location
with result
Row date location revenue date_last_year revenue_last_year
1 2018-02-20 A 1 2017-02-20 0
2 2018-02-20 B 2 2017-02-20 0
3 2018-02-21 A 3 2017-02-21 0
4 2018-02-22 B 4 2017-02-22 0
5 2019-02-20 A 5 2018-02-20 1
6 2019-02-20 B 6 2018-02-20 2
7 2019-02-21 A 7 2018-02-21 3
8 2019-02-21 B 8 2018-02-21 0
9 2019-02-22 A 9 2018-02-22 0
10 2019-02-22 B 10 2018-02-22 4

Related

Mysql calculate sum of daily hours worked from clockin and clockout, when shift spans across midnight, or multiple days

I have a table with userID, clockin(1)/Clockout(0), dateTime for few employees. in/out shows when someone is on (1) or off(0) clock.
Job shift can span across midnight, as in punch in before midnight, and punchout in the morning. (Eg: Date 21st in table)
Shift can last more than 24 hours (hypothetically) (Eg : Date 24)
Punchin and punchout can happen multiple times within 24 hrs as well(Eg : Date 22).
I would like to get the sum of hours worked per day for any given user_id but within midnight to midnight, even though the shift might span across midnight. Timestamps are shown all with :30:00 for clarity. Only one user_id is shown, but this table can have info from multiple users, so user_id will be used in the where clause.
[id] [User_id] [Date_time] [in_out]
1 1 2022-08-20 09:30:00 1
2 1 2022-08-20 21:30:00 0
3 1 2022-08-21 20:30:00 1
4 1 2022-08-22 08:30:00 0
5 1 2022-08-22 09:30:00 1
6 1 2022-08-22 14:30:00 0
7 1 2022-08-23 12:30:00 1
8 1 2022-08-25 09:30:00 0
9 1 2022-08-25 12:30:00 1
So The desired query result would be something like below. The formatting does not matter. Total time per day in seconds or minutes or anything will work.
[Day] [hours_worked]
2022-08-20 12:00:00
2022-08-21 03:30:00
2022-08-22 13:00:00
2022-08-23 11:30:00
2022-08-24 24:00:00
2022-08-25 09:30:00
I started with the code from Get total hours worked in a day mysql This works well when punch-in happens before punch outs in a day, and does not handle midnights. Just trying to adapt to the specific case. Any help much appreciated.
To do this in MySQL 5.6, I can only think of a not so nice query, but let's create the data first
CREATE TABLE events
(`id` int, `User_id` int, `Date_time` datetime, `in_out` int);
INSERT INTO events
(`id`, `User_id`, `Date_time`, `in_out`)
VALUES
(1, 1, '2022-08-20 09:30:00', 1),
(2, 1, '2022-08-20 21:30:00', 0),
(3, 1, '2022-08-21 20:30:00', 1),
(4, 1, '2022-08-22 08:30:00', 0),
(5, 1, '2022-08-22 09:30:00', 1),
(6, 1, '2022-08-22 14:30:00', 0),
(7, 1, '2022-08-23 12:30:00', 1),
(8, 1, '2022-08-25 09:30:00', 0),
(9, 1, '2022-08-25 12:30:00', 1);
Based on https://stackoverflow.com/a/60173743/19657183, one can get the dates for every single day between the first and last event date. Then, you can JOIN the result with the events to figure out the ones which overlap. From that you can calculate the time differences and sum them up grouped by day:
SELECT User_id, start_of_day,
sec_to_time(sum(timestampdiff(SECOND, CAST(GREATEST(cast(start_of_day as datetime), prev_date_time) AS datetime),
CAST(LEAST(start_of_next_day, Date_time) AS datetime)))) AS diff
FROM (
SELECT * FROM (
SELECT id, User_id,
CASE WHEN #puid IS NULL or #puid <> User_id THEN NULL ELSE #pdt END AS prev_date_time, #pdt := Date_time AS Date_time,
CASE WHEN #puid IS NULL or #puid <> User_id THEN NULL ELSE #pio END AS prev_in_out, #pio := in_out in_out,
#puid := User_id
FROM (SELECT * FROM events ORDER BY User_id, Date_time) e,
(SELECT #pdt := '1970-01-01 00:00:00', #pio := NULL, #puid := NULL) init ) tr
WHERE prev_in_out = 1 and in_out = 0) event_ranges
JOIN (
SELECT #d start_of_day,
#d := date_add(#d, interval 1 day) start_of_next_day
FROM (SELECT #d := date(min(Date_time)) FROM events) min_d,
(SELECT x1.N + x10.N*10 + x100.N*100 + x1000.N*1000
FROM (SELECT 0 AS N 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) x1,
(SELECT 0 AS N 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) x10,
(SELECT 0 AS N 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) x100,
(SELECT 0 AS N 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) x1000
WHERE x1.N + x10.N*10 + x100.N*100 + x1000.N*1000 <= (SELECT date(max(Date_time)) - date(min(Date_time)) FROM events)) days_off) day_ranges
ON prev_date_time < start_of_next_day AND Date_time >= start_of_day
GROUP BY User_id,start_of_day;
I encountered a problem using sqlfiddle.com: it returned 00:00:00 if e.g. the time difference was exactly 24 hours (didn't matter if I used timediff or sec_to_time). I haven't seen this problem neither on MySQL 8 nor in db-fiddle.com (using MySQL 5.6). So, it might be, that you've to work around this problem.
EDIT: rewrote completely to solve the problem in MySQL 5.6 as requested by the OP.
EDIT #2: Updated the query to take sorting and grouping into account.
EDIT #3: changed initial assignment of the variables.

MYSQL SUM until last day of Each month for last 12 months

I have a table like this two
Table A
date amount B_id
'2020-1-01' 3000000 1
'2019-8-01' 15012 1
'2019-6-21' 90909 1
'2020-1-15' 84562 1
--------
Table B
id type
1 7
2 5
I have to show sum of amount until the last date of each month for the last 12 month.
The query i have prepared is like this..
SELECT num2.last_dates,
(SELECT SUM(amount) FROM A
INNER JOIN B ON A.B_id = B.id
WHERE B.type = 7 AND A.date<=num2.last_dates
),
(SELECT SUM(amount) FROM A
INNER JOIN B ON A.B_id = B.id
WHERE B.type = 5 AND A.date<=num2.last_dates)
FROM
(SELECT last_dates
FROM (
SELECT LAST_DAY(CURDATE() - INTERVAL CUSTOM_MONTH MONTH) last_dates
FROM(
SELECT 1 CUSTOM_MONTH UNION
SELECT 0 UNION
SELECT 2 UNION
SELECT 3 UNION
SELECT 4 UNION
SELECT 5 UNION
SELECT 6 UNION
SELECT 7 UNION
SELECT 8 UNION
SELECT 9 UNION
SELECT 10 UNION
SELECT 11 UNION
SELECT 12 )num
) num1
)num2
ORDER BY num2.last_dates
This gives me the result like this which is exactly how i need it. I need this query to execute faster. Is there any better way to do what i am trying to do?
2019-05-31 33488.69 109.127800
2019-06-30 263.690 1248932.227800
2019-07-31 274.690 131.827800
2019-08-31 627.690 13.687800
2019-09-30 1533.370000 08.347800
2019-10-31 1444.370000 01.327800
2019-11-30 5448.370000 247.227800
2019-12-31 61971.370000 016.990450
2020-01-31 19550.370000 2535.185450
2020-02-29 986.370000 405.123300
2020-03-31 1152.370000 26.793300
2020-04-30 9404.370000 11894.683300
2020-05-31 3404.370000 17894.683300
I'd use conditional aggregation, and pre-aggregate the monthly totals in one pass, instead of doing twenty-six individual passes repeatedly through the same data.
I'd start with something like this:
SELECT CASE WHEN A.date < DATE(NOW()) + INTERVAL -14 MONTH
THEN LAST_DAY( DATE(NOW()) + INTERVAL -14 MONTH )
ELSE LAST_DAY( A.date )
END AS _month_end
, SUM(IF( B.type = 5 , B.amount , NULL)) AS tot_type_5
, SUM(IF( B.type = 7 , B.amount , NULL)) AS tot_type_7
FROM A
JOIN B
ON B.id = A.B_id
WHERE B.type IN (5,7)
GROUP
BY _month_end
(column amount isn't qualified in original query, so just guessing here which table that is from. adjust as necessary. best practice is to qualify all column references.
That gets us the subtotals for each month, in a single pass through A and B.
We can get that query tested and tuned.
Then we can incorporate that as an inline view in an outer query which adds up those monthly totals. (I'd do an outer join, just in case rows are missing, sow we don't wind up omitting rows.)
Something like this:
SELECT d.dt + INTERVAL -i.n MONTH + INTERVAL -1 DAY AS last_date
, SUM(IFNULL(t.tot_type_5,0)) AS rt_type_5
, SUM(IFNULL(t.tot_type_7,0)) AS rt_type_7
FROM ( -- first day of next month
SELECT DATE(NOW()) + INTERVAL -DAY(DATE(NOW()))+1 DAY + INTERVAL 1 MONTH AS dt
) d
CROSS
JOIN ( -- thirteen integers, integers 0 thru 12
SELECT 0 AS n
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 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
) i
LEFT
JOIN ( -- totals by month
SELECT CASE WHEN A.date < DATE(NOW()) + INTERVAL -14 MONTH
THEN LAST_DAY( DATE(NOW()) + INTERVAL -14 MONTH )
ELSE LAST_DAY( A.date )
END AS _month_end
, SUM(IF( B.type = 5 , B.amount , NULL)) AS tot_type_5
, SUM(IF( B.type = 7 , B.amount , NULL)) AS tot_type_7
FROM A
JOIN B
ON B.id = A.B_id
WHERE B.type IN (5,7)
GROUP
BY _month_end
) t
ON t._month_end < d.dt
GROUP BY d.dt + INTERVAL -i.n MONTH + INTERVAL -1 DAY
ORDER BY d.dt + INTERVAL -i.n MONTH + INTERVAL -1 DAY DESC
The design is meant to do one swoop through the A JOIN B set. We're expecting to get about 14 rows back. And we're doing a semi-join, duplicating the oldest months multiple times, so approx . 14 x 13 / 2 = 91 rows, that get collapsed into 13 rows.
The big rock in terms of performance is going to be materializing that inline view query.
This is how I'd probably approach this in MySQL 8 with SUM OVER:
Get the last 12 months.
Use these months to add empty month rows to the original data, as MySQL doesn't support full outer joins.
Get the running totals for all months.
Show only the last twelve months.
The query:
with months (date) as
(
select last_day(current_date - interval 1 month) union all
select last_day(current_date - interval 2 month) union all
select last_day(current_date - interval 3 month) union all
select last_day(current_date - interval 4 month) union all
select last_day(current_date - interval 5 month) union all
select last_day(current_date - interval 6 month) union all
select last_day(current_date - interval 7 month) union all
select last_day(current_date - interval 8 month) union all
select last_day(current_date - interval 9 month) union all
select last_day(current_date - interval 10 month) union all
select last_day(current_date - interval 11 month) union all
select last_day(current_date - interval 12 month)
)
, data (date, amount, type) as
(
select last_day(a.date), a.amount, b.type
from a
join b on b.id = a.b_id
where b.type in (5, 7)
union all
select date, null, null from months
)
select
date,
sum(sum(case when type = 5 then amount end)) over (order by date) as t5,
sum(sum(case when type = 7 then amount end)) over (order by date) as t7
from data
group by date
order by date
limit 12;
Demo: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=ddeb3ab3e086bfc182f0503615fba74b
I don't know whether this is faster than your own query or not. Just give it a try. (You'd get my query much faster by adding a generated column for last_day(date) to your table and use this. If you need this often, this may be an option.)
You are getting some complicated answers. I think it is easier. Start with knowing we can easily sum for each month:
SELECT SUM(amount) as monthtotal,
type,
MONTH(date) as month,
YEAR(date) as year
FROM A LEFT JOIN B on A.B_id=B.id
GROUP BY type,month,year
From that data, we can use a variable to get running total. Best to do by initializing the variable, but not necessary. We can get the data necessary like this
SET #running := 0;
SELECT (#running := #running + monthtotal) as running, type, LAST_DAY(CONCAT(year,'-',month,'-',1))
FROM
(SELECT SUM(amount) as monthtotal,type,MONTH(date) as month,YEAR(date) as year FROM A LEFT JOIN B on A.B_id=B.id GROUP BY type,month,year) AS totals
ORDER BY year,month
You really need to have a connector that supports multiple statements, or make multiple calls to initialize the variable. Although you can null check the variable and default to 0, you still have an issue if you run the query a second time.
Last thing, if you really want the types to be summed separately:
SET #running5 := 0;
SET #running7 := 0;
SELECT
LAST_DAY(CONCAT(year,'-',month,'-',1)),
(#running5 := #running5 + (CASE WHEN type=5 THEN monthtotal ELSE 0 END)) as running5,
(#running7 := #running7 + (CASE WHEN type=7 THEN monthtotal ELSE 0 END)) as running7
FROM
(SELECT SUM(amount) as monthtotal,type,MONTH(date) as month,YEAR(date) as year FROM A LEFT JOIN B on A.B_id=B.id GROUP BY type,month,year) AS totals
ORDER BY year,month
We still don't show months where there is no data. I'm not sure that is a requirement. But this should only need one pass of table A.
Also, make sure the id on table B is indexed.

Bigquery mysql to adjust dates for active weekdays

In a previous question the answer was given to perform a query which would get revenue from the last year in a new column. This worked perfectly, but now I have a follow-up question. (please review this link to have a look at the previous question)
The query used to get this data (With thanks to Mikhail):
#standardSQL
SELECT
a.date, a.location, a.revenue,
DATE_SUB(a.date, INTERVAL 1 YEAR) date_last_year,
IFNULL(b.revenue, 0) revenue_last_year
FROM `project.dataset.table` a
LEFT JOIN `project.dataset.table` b
ON a.location = b.location
AND DATE_SUB(a.date, INTERVAL 1 YEAR) = b.date
The simplified outcome looks as follows (limited to 1 location):
date revenue revenue_last_year
2019-01-31 1471,2577 2185,406
2019-01-30 1291,1111 4723,7439
2019-01-29 2178,6532 2263,5283
2019-01-28 1531,8021 0
2019-01-26 1578,1247 2446,6234
2019-01-25 1299,644 1522,4537
2019-01-24 788,2669 1979,104
2019-01-23 787,441 4117,7927
2019-01-22 2437,2951 1876,2479
2019-01-21 1071,0476 0
2019-01-19 2291,0456 2289,8657
The follow up question relates to working with weekdays from last year. As you can see the revenue last year has '0' values. That's because it's a day that location A was closed. However, to make an accurate comparison on a day by day basis we need to locate the revenue for the day this revenue was open.
For more information, have a look at this table below to see what it looks like when we take the last 10 days of Jan this year and append two columns with the revenues of last year found manually:
date revenue revenue_last_year date revenue
2019-01-31 1471,2577 2185,406 2018-01-31 2185,406
2019-01-30 1291,1111 4723,7439 2018-01-30 4723,7439
2019-01-29 2178,6532 2263,5283 2018-01-29 2263,5283
2019-01-28 1531,8021 0 2018-01-27 2843,6616
2019-01-26 1578,1247 2446,6234 2018-01-26 2446,6234
2019-01-25 1299,644 1522,4537 2018-01-25 1522,4537
2019-01-24 788,2669 1979,104 2018-01-24 1979,104
2019-01-23 787,441 4117,7927 2018-01-23 4117,7927
2019-01-22 2437,2951 1876,2479 2018-01-22 1876,2479
2019-01-21 1071,0476 0 2018-01-20 2561,4086
2019-01-19 2291,0456 2289,8657 2018-01-19 2289,8657
Please note the differences in dates.
What would be a good way to solve this? Would it be necessary to adjust to a query for weekdays and how would you approach this?
Below is for BigQuery Standard SQL
#standardSQL
SELECT
a.date, a.location, ANY_VALUE(a.revenue) revenue,
ARRAY_AGG(
STRUCT(b.date AS date_last_year, b.revenue AS revenue_last_year)
ORDER BY b.date DESC LIMIT 1
)[OFFSET(0)].*
FROM `project.dataset.table` a
CROSS JOIN `project.dataset.table` b
WHERE a.location = b.location
AND b.date BETWEEN DATE_SUB(DATE_SUB(a.date, INTERVAL 1 YEAR), INTERVAL 7 DAY) AND DATE_SUB(a.date, INTERVAL 1 YEAR)
GROUP BY a.date, a.location
You can test, play with above using dummy/sample data (I used same as in my answer for your previous question) as in below example
#standardSQL
WITH `project.dataset.table` AS (
SELECT DATE '2018-02-20' `date`, 'A' location, 1 revenue UNION ALL
SELECT '2018-02-21', 'A', 3 UNION ALL
SELECT '2019-02-20', 'A', 5 UNION ALL
SELECT '2019-02-21', 'A', 7 UNION ALL
SELECT '2019-02-22', 'A', 9 UNION ALL
SELECT '2018-02-20', 'B', 2 UNION ALL
SELECT '2018-02-22', 'B', 4 UNION ALL
SELECT '2019-02-20', 'B', 6 UNION ALL
SELECT '2019-02-21', 'B', 8 UNION ALL
SELECT '2019-02-22', 'B', 10
)
SELECT
a.date, a.location, ANY_VALUE(a.revenue) revenue,
ARRAY_AGG(
STRUCT(b.date AS date_last_year, b.revenue AS revenue_last_year)
ORDER BY b.date DESC LIMIT 1
)[OFFSET(0)].*
FROM `project.dataset.table` a
CROSS JOIN `project.dataset.table` b
WHERE a.location = b.location
AND b.date BETWEEN DATE_SUB(DATE_SUB(a.date, INTERVAL 1 YEAR), INTERVAL 7 DAY) AND DATE_SUB(a.date, INTERVAL 1 YEAR)
GROUP BY a.date, a.location
-- ORDER BY a.date, a.location
with result
Row date location revenue date_last_year revenue_last_year
1 2019-02-20 A 5 2018-02-20 1
2 2019-02-20 B 6 2018-02-20 2
3 2019-02-21 A 7 2018-02-21 3
4 2019-02-21 B 8 2018-02-20 2
5 2019-02-22 A 9 2018-02-21 3
6 2019-02-22 B 10 2018-02-22 4
Note the differences in dates :o)

SQL to get number count per minute

I have a dataset like:
id name updated_at
1 test1 2014-06-30 09:00:00
1 test2 2014-06-30 09:01:10
1 test3 2014-06-30 09:01:23
1 test4 2014-06-30 09:01:43
1 test5 2014-06-30 09:02:02
1 test6 2014-06-30 09:02:34
1 test7 2014-06-30 09:03:22
1 test8 2014-06-30 09:03:28
I need to get a count of the rows by minute for the last ten minutes. So it should always return ten numbers being the count of the rows that were updated last. Any ideas on how to do it and efficiently?
Last 10 Results
http://sqlfiddle.com/#!9/3d586/22
--get the minute component of the update time
select minute(updated_at) as Sec
--count the number of records which have this minute
, count(1) as Cnt
from myTable
--use group by to ensure we return 1 row per minute
group by minute(updated_at)
--list from most recent working backwards
order by minute(updated_at) desc
--return up to 10 results
limit 10
Results for last 10 minutes
http://sqlfiddle.com/#!9/3d586/26
--get the minute component of the update time
select minute(y.d) as Min
--count the number of records which have this minute
--use m.id instead of 1 or * to ensure where there's no result from myTable
--we don't count any rows
, count(m.id) as Cnt
from
(
--get the current date's minute, offset by a given amount
select date_add(now(), interval -x.a minute) d
from
(
--the list of given amounts by which to offset the above date
select 0 a
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
) x
) y
--left join to ensure the above list drives which results we get,
--regardless of whether there are matching entries in myTable
left outer join myTable m
--join on the minute of each date
on minute(m.updated_at) = minute(y.d)
--use group by to ensure we return 1 row per minute
group by minute(y.d)
--list from most recent working backwards
order by minute(y.d) desc
Since you want interpolated values, it quickly becomes more complicated. It's probably easiest just to create a derived table with every minute from the last ten minutes as a row, then left join to that. Here's one way to do it:
select minute(now() - interval m minute) 'minutes ago', count(case when t.updated_at is not null then t.updated_at end)
from
(select minute(now()) m
union
select minute(now() - interval 1 minute) m
union
select minute(now() - interval 2 minute) m
union
select minute(now() - interval 3 minute) m
union
select minute(now() - interval 4 minute) m
union
select minute(now() - interval 5 minute) m
union
select minute(now() - interval 6 minute) m
union
select minute(now() - interval 7 minute) m
union
select minute(now() - interval 8 minute) m
union
select minute(now() - interval 9 minute) m
union
select minute(now() - interval 10 minute) m
) q
left join myTable t
on q.m = minute(t.updated_at)
and t.updated_at >= now() - interval 10 minute
group by m
order by m desc
There's a fiddle here but you'll have to alter the schema (just add a space somewhere) and rebuild it in order to get accurate results:
http://sqlfiddle.com/#!9/f3320/1

get average value depending on month?

My table:
rating date
4 12/02/2013
3 12/02/2013
2.5 12/01/2013
3 12/01/2013
4.5 21/11/2012
5 10/11/2012
If I give input as 3 the last three months (02,01,12), average of rating result should come
I tried by using GROUP BY but I get this result:
rating month
3.5 02
2.75 01
For the 12th month no rating so no output.....
My desired result:
rating month
3.5 02
2.75 01
0 12
The problem is that you want to return months that do not exist. If you do not have a calendar table with dates, then you will want to use something like the following:
select d.mth Month,
coalesce(avg(t.rating), 0) Rating
from
(
select 1 mth union all
select 2 mth union all
select 3 mth union all
select 4 mth union all
select 5 mth union all
select 6 mth union all
select 7 mth union all
select 8 mth union all
select 9 mth union all
select 10 mth union all
select 11 mth union all
select 12 mth
) d
left join yourtable t
on d.mth = month(t.date)
where d.mth in (1, 2, 12)
group by d.mth
See SQL Fiddle with Demo
SELECT coalesce(avg(rating), 0.0) avg_rating, req_month
FROM yourTable
RIGHT JOIN
(SELECT month(now()) AS req_month
UNION
SELECT month(now() - INTERVAL 1 MONTH) AS req_month
UNION
SELECT month(now() - INTERVAL 2 MONTH) AS req_month) tmpView
ON month(yourTable.date) = tmpView.req_month
WHERE yourTable.date > ( (curdate() - INTERVAL day(curdate()) - 1 DAY) - INTERVAL 2 MONTH)
OR ratings.datetime IS NULL
GROUP BY month(yourTable.date);