SQL Order by 2 conditions - mysql

Let's say that I have a database, that looks like that:
price date hour
12.00 2018-12-11 5
13.00 2018-12-04 2
14.00 2018-12-06 1
15.00 2018-12-11 1
16.00 2018-12-04 6
17.00 2018-12-06 10
I need to order by date and if days are the same after hour, so results should be:
price date hour
13.00 2018-12-04 2
16.00 2018-12-04 6
14.00 2018-12-06 1
17.00 2018-12-06 10
15.00 2018-12-11 1
12.00 2018-12-11 5
I tried to write a simple query, but it couldn't take into account 2 conditions, one after another:
SELECT price, date, hour
FROM table
WHERE date BETWEEN '2018-12-04' AND '2018-12-11'
ORDER BY date, hour
Could anyone help with this issue ?
Thanks All !

The only real issue I can think of would be if hour were stored as a string. If so, use implicit conversion:
SELECT price, date, hour
FROM table
WHERE date BETWEEN '2018-12-04' AND '2018-12-11'
ORDER BY date, hour + 0;

A simple ORDER BY will suffice:
select * from my_table order by `date`, hour;
Please note the date is usually a reserved word, so its usage is discouraged, and needs to be quoted.

Related

Calculate MRR Kpi without monthly invoices

I am trying to calculate mrr for each month.
The DB table 'boxes' looks like this:
project_id
product_id
payment_method_id
price
interval
booked_at
canceled_at
1
1
3
19.00
1
2020-12-01 00:00:00
NULL
1
2
3
39.00
1
2020-05-01 00:00:00
2020-11-05 19:10:27
4
1
3
39.00
12
2020-05-01 00:00:00
2020-11-05 19:10:27
Payment-Interval is in months. I need to show in KPI dashboard the mrr.
Currently I have this query:
SELECT DATE_FORMAT(booked_at, '%Y-%m') AS period, sum(price)
FROM
project_boxes
GROUP BY period;
The problem with the above query is that it doesn't show between months MRR and doesn't work with canceled boxes.
What am I missing? Any help is appreciated.

How to do Week over Week Increase in SQL [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
ads Table:
-one row per ad per day
date | ad_id | account_id | spend
2018-05-01 123 1101 100
2018-05-02 123 1101 125
2018-05-03 124 1101 150
2018-05-04 124 1101 150
2018-05-04 125 1105 150
2018-05-04 126 1105 150
2018-05-04 123 1101 150
2018-01-01 123 1101 150
I am trying to write a query to find out: on each day, the total spend and the week-over-week change since 1st January.
So, week over week should show 8th day's total spending - 1st days total spending. I can achieve that lag window function but what I am not sure what to do if the first day is not mentioned in the date column. Let's say there's no spending on the first day of may then the answer would go wrong if I had used lag function. Is there a way that I could write a query that would look for the total spending through dates rather than lag function? and if on the first day I have no spending, I could get 1200-0=1200 is the WOW change. Also, I can't create a dates table that I can join the ads table on.
I have written this much so far:
select dates, sum(spend) "total_spend_each_day",
from fb_ads as f
where dates>= '2018-01-01'
group by dates
order by 1;
Desired Output:
date | total_spend_each_day | Week_over_week_change
2018-05-01 500 Null
2018-05-02 600 Null
2018-05-03 700 Null
2018-05-04 800 Null
2018-05-05 900 Null
2018-05-06 1000 Null
2018-01-07 1100 Null
2018-01-08 1200 700
Just use lag(). Assuming you have at least one record per day:
select dates, sum(spend) as total_spend_each_day,
sum(spend) - lag(sum(spend), 7) over (order by dates) as diff
from fb_ads as f
where dates >= '2018-01-01'
group by dates
order by 1;
If you don't have data for each day, then just use a window frame with range():
select dates, sum(spend) as total_spend_each_day,
(sum(spend) -
max(sum(spend)) over (order by dates range between interval 7 day and interval 7 day)
) as diff
from fb_ads as f
where dates >= '2018-01-01'
group by dates
order by 1;

MariaDb/MySQL sliding sum over 24 hours

My table have fields that represent starting and ending working period as datetime.
I need to find related entries that match a total of 14hours min over a sliding period of 24 hours.
I think window function will (maybe) save me, but MariadDB (i use) doesn't implement yet Range time intervals in window function.
here is some example data:
id starting_hour ending_hour
-- ------------------- -------------------
1 2018-09-02 06:00:00 2018-09-02 08:30:00
2 2018-09-03 08:30:00 2018-09-03 10:00:00
4 2018-09-03 11:00:00 2018-09-03 15:00:00
5 2018-09-02 15:30:00 2018-09-02 16:00:00
6 2018-09-02 16:15:00 2018-09-02 17:00:00
7 2018-09-20 00:00:00 2018-09-20 08:00:00
8 2018-09-19 10:00:00 2018-09-19 12:00:00
9 2018-09-19 12:00:00 2018-09-19 16:00:00
10 2018-10-08 12:00:00 2018-10-08 14:00:00
11 2018-10-29 09:00:00 2018-10-29 10:00:00
So how to find rows where in a 24 hours window their sum a more or equal to 14 hours.
thanks
Edit:
SELECT
id,
starting_hour,
ending_hour,
TIMEDIFF (ending_hour, starting_hour) AS duree,
(
SELECT SUM(TIMEDIFF(LEAST(ending_hour, DATE_ADD(a.starting_hour, INTERVAL 24 HOUR)), starting_hour)) / 10000
FROM `table` b
WHERE b.starting_hour BETWEEN a.starting_hour AND DATE_ADD(a.starting_hour, INTERVAL 24 HOUR)
) AS duration
FROM
`table` a
HAVING duration >= 14
ORDER BY starting_hour ASC
;
This returns Id 8 but i want the whole period. (eg: Id 8, Id 9 and Id 7)
EDIT2:
The expected results are ranges of working time where they are in a window of 24 hours and where their sum are more or equal to 14 hours.
EDIT 3:
In fact under MySQL 8 this seems to work.
SELECT * FROM (
SELECT
*,
SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(hs.`ending_hour`, hs.`starting_hour`))) OVER (ORDER BY hs.starting_hour RANGE BETWEEN INTERVAL '12' HOUR PRECEDING AND INTERVAL '12' HOUR following)) AS tot
FROM
table hs
WHERE hs.`starting_hour` > DATE_SUB(NOW(), INTERVAL 50 DAY) AND hs.`ending_hour` <= NOW()
ORDER BY hs.`starting_hour` ASC
) t1
HAVING tot >= '14:00:00'
;
Is there a way to do it under MariaDB 10.2 without window function ? Or without window range function ?

Select query that outputs counts of rows that are within a certain time period

My question is little bit more complicated than what the title implies but here it is:
I have a table with punch data formatted like this:
name time_in time_out location
1 2018-05-31 10:09:00 2018-05-31 16:06:00 1
3 2018-05-31 10:12:00 2018-05-31 17:03:00 1
I would like a select query that returns the total time in hours of people that are working during a 15min time frame for each location. Here is an example output for the two rows given:
time labor_hours location
2018-05-31 10:00:00 .15 1
2018-05-31 10:15:00 .50 1
2018-05-31 10:30:00 .50 1
2018-05-31 10:45:00 .50 1
2018-05-31 11:00:00 .50 1
...
2018-05-31 15:45:00 .50 1
2018-05-31 16:00:00 .35 1
2018-05-31 16:15:00 .25 1
2018-05-31 16:30:00 .25 1
2018-05-31 16:45:00 .25 1
2018-05-31 17:00:00 .10 1
Labor hours is total hours worked during a 15min time period in hours. So for example, the first row was calculated by looking at the first two rows and seeing that from 10:00:00 - 10:15:00 employee 1 and 2 worked for a total of 9 minutes. Since it's in hours 9/60 = .15.
I'm new to sql so I'm pretty lost on how to start with this.
If you are using MySQL 8.0, you can use the CTE feature as follows
WITH cte (timeStamp) AS
(
SELECT "2018-05-31 00:00:00"
UNION ALL
SELECT TIMESTAMPADD(MINUTE, 15, timeStamp)
WHERE timeStamp < 2018-06-01 00:00:00
)
SELECT timeStamp FROM cte;
SELECT cte.time,
sum(TIMESTAMPDIFF(MINUTE, punch.time,
TIMESTAMPAD(MINUTE, 15, cte.timeStamp))) as labour_hours,
punch.location
FROM cte LEFT OUTER JOIN punch ON punch.time >=cte.timeStamp
AND punch.time < TIMESTAMPADD(MINUTE, 15, cte.timeStamp)
GROUP BY punch.location, cte.timeStamp
If you are using an older version of MySQL, you need to create a stored procedure that generates the timestamps with 15 minute intervals.

Select rows from last existing 12 months

There's a DATETIME column called time. How could I select all rows that fall within the last existing 12 months (NOT within the last year from today)? Not every month might have a row, and months may have more than one row.
For example, out of this table (ORDER BY time DESC), rows with ids 2 to 17 would be selected.
id time
-- ----
17 2015-04-01
16 2015-04-01
15 2015-03-01
14 2015-02-01
13 2015-01-01
12 2014-12-01
11 2014-11-01
10 2014-10-01
9 2013-12-01
8 2013-11-01
7 2013-10-01
6 2013-09-01
5 2013-09-01
4 2013-09-01
3 2013-09-01
2 2013-08-01
1 2013-07-01
Another way to put this:
Take the table above and group by month/year, so we get:
2015-04
2015-03
2015-02
2015-01
2014-12
2014-11
2014-10
2013-12
2013-11
2013-10
2013-09
2013-08
2013-07
Now take the 12 most recent months from this list, which is everything except 2013-07.
2015-04
2015-03
2015-02
2015-01
2014-12
2014-11
2014-10
2013-12
2013-11
2013-10
2013-09
2013-08
And select everything from those months.
I guess I could do this with multiple queries or subqueries but is there another way to do this?
If your time field is only month-precision, you could do it with a pretty simple subselect:
SELECT * FROM Table t1
WHERE time IN (
SELECT DISTINCT time FROM Table t2 ORDER BY time DESC LIMIT 12
)
If your timestamps are full-precision, you could do the same thing, but you'd need to do some date manipulation to round the dates to the month for comparison.