Query to select intervals in day - mysql

I have table something like this (there's also "device_id" and "timestamp" columns)
day | interval | value
----------------------------
1 | 14 | 63 // start of a day
1 | 14 | 83
1 | 14 | 73
1 | 15 | 23
1 | 15 | 33
1 | 15 | 50
2 | 16 | 23 // start of a day
2 | 16 | 33
2 | 16 | 50
I want to select all intervals in a day. That is simple.
However, an interval can start a bit before a day flips, or end a bit past:
day | interval | value
----------------------------
7 | 14 | 63
7 | 14 | 83
8 | 14 | 73 // start of a day
8 | 15 | 23
8 | 15 | 33
8 | 15 | 50
8 | 16 | 23
8 | 16 | 33
9 | 16 | 50 // start of a day
Now I'd like to select all three intervals - or even better intervals that are mostly in that day.
SELECT ... WHERE day = 8
Gives me only parts of the start/end intervals (14, 16). That's useless, I need the complete intervals.
If there's no solution, I'll just do three queries, but there might be some SQL trick I'm not aware of?
It's MySQL, called from PHP.
More visually:
day 7 | day 8 | day 9
------------------+-------------------+---------------
###13### ###14### ###15### ###16### ###17###
... 63 83 73 23 33 50 23 33 50 ...
I want all values in day 8 -> intervals 14, 15, 16

I think you are looking for this:
SELECT * FROM intervals
WHERE interval IN (
SELECT DISTINCT interval FROM intervals WHERE day = 8)
This selects all interval data where at least one of the entries for that interval occurs in day 8. The subquery determines which unique intervals happen in the day, which is then used by the outer query to select their specifics.

SELECT DISTINCT y.*
FROM my_table x
JOIN my_table y
ON y.some_column = x.some_column
WHERE x.some_other_column = 8;

Related

Mysql get weekly average of daily data

I have a table called primeWeek. Im trying to get weekly avg depends on dates.
Example of my table
id | count | date
1 | 70 | 2020-08-29
2 | 67 | 2020-08-30
3 | 69 | 2020-08-31
4 | 82 | 2020-09-01
5 | 73 | 2020-09-02
I tried few things but results are not correct.
count and date are both keywords in SQL, so you should surround them with backticks.
SELECT
AVG(`count`) AS primeCount,
CONCAT(`date`, '-', `date` + INTERVAL 6 DAY) AS week
FROM primeWeek
GROUP BY WEEK(`date`)
ORDER BY WEEK(`date`);

How to write an SQL query to calculate the average for three consecutive values?

I have a table like this
userID time NoOfVisits
1 2014 50
2 2015 60
3 2016 70
4 2017 80
5 2018 90
6 2019 100
I need to write a sql query which will print time and average of past 3 years NoOfVisits for a particular site.
output should be as
userID time NoOfVisits
1 2014 50.0000
2 2015 55.0000
3 2016 60.0000
4 2017 70.0000
5 2018 80.0000
6 2019 90.0000
Explanation :
For user Id 6 (80+90+100)/3=90.0000
Please help me to solve this problem.
You can use a cumulative average, available in MySQL 8+:
select t.*,
avg(visits) over (order by time rows between 2 preceding and current row) as avg_visits_3
from t;
Assuming there are no gaps between the years (like your sample data), you can self join the table and group by userid, time to get the average:
select
t.userid, t.time, avg(tt.noofvisits) NoOfVisits
from tablename t inner join tablename tt
on tt.time between t.time - 2 and t.time
group by t.userid, t.time
See the demo.
Results:
| userid | time | NoOfVisits |
| ------ | ---- | ---------- |
| 1 | 2014 | 50 |
| 2 | 2015 | 55 |
| 3 | 2016 | 60 |
| 4 | 2017 | 70 |
| 5 | 2018 | 80 |
| 6 | 2019 | 90 |

SQL max date related issue

I'm having a bit of an issue with max(date) in SQL.
Basically the problem being that I have to check if latest date entered by id is more than 1 days old and then return that date.
id| user_id| send_date
8 | 90 | 2016-10-21 14:31:14
| 10 | 90 | 2016-10-25 09:56:28
| 11 | 18 | 2016-10-22 09:56:28
| 12 | 19 | 2016-10-21 09:56:28
| 13 | 19 | 2016-10-23 09:56:28
| 13 | 20 | 2016-10-25 09:56:28
This is part of a much longer SQL (just the part that I have a problem with):
SELECT max(h.send_date) as lastSent
FROM history h
WHERE (h.send_date < NOW() - INTERVAL 1 DAY);
Now what happens is that instead of selecting rows where latest entered date is older than 1 day, I get the latest one that is older than 1 day even if there's a newer entry in the table.
Does anyone have an idea how to change it so that SQL would only return the latest date when it's older that 24h and the newest (by user) in the table (in the example, it would have to return nothing because there's an entry less than 24h old)?
Edited the table example a bit. This is what I need to get as a result (user_ids 90 and 20 get's ignored because of 2016-10-25 09:56:28):
18 | 2016-10-22 09:56:28
19 | 2016-10-23 09:56:28
for aggregation function you should use having and not where
SELECT max(h.send_date) as lastSent
FROM history h
having max(h.send_date ) < DATE_SUB(NOW() ,INTERVAL 1 DAY) ;

SQL Server 2008 : CASE WHEN auto increments/groups data

I have a table that stores data like the below :
MonthOpened | MONTH | Collected
--------------------------------
01/05/2012 | 1 | £10.00
01/05/2012 | 2 | £30.00
01/05/2012 | 3 | £30.00
01/05/2012 | 4 | £30.00
01/05/2012 | 5 | £30.00
01/05/2012 | 6 | £10.00
01/05/2012 | 7 | £30.00
01/05/2012 | 8 | £50.00
01/05/2012 | 9 | £10.00
01/05/2012 | 10 | £50.00
01/05/2012 | 11 | £100.00
01/05/2012 | 12 | £141.92
01/05/2012 | 13 | £100.00
01/05/2012 | 14 | £50.00
Month opened is the date the accounts where taken out, Month is the month that they paid (month 1 is the month the account was opened (may), month 2 would be June, month 3 would be july and so on. At the moment this goes all the way through to month 36.
For reference this data goes into a SSRS Matrix and appears like so
MONTH |1 |2 | 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14
----------------------------------------------------------------------------------------------------------------
01/05/2012|£10.00|£30.00|£30.00|£30.00|£30.00|£10.00|£30.00|£50.00|£10.00|£50.00|£100.00|£141.92|£100.00|£50.00
I've been asked to group these together after 12 months, so 1-12 appear, then 18, 24, 30, 36 and so on. I've done this as a quick fix by doing a generic case when
CASE
WHEN ISNULL(sp.Month, N'01') BETWEEN 01 AND 12
THEN ISNULL(sp.Month, N'01')
WHEN ISNULL(sp.Month, N'01') BETWEEN 13 AND 18
THEN 18
WHEN ISNULL(sp.Month, N'01') BETWEEN 19 AND 24
THEN 24
WHEN ISNULL(sp.Month, N'01') BETWEEN 25 AND 30
THEN 30
WHEN ISNULL(sp.Month, N'01') BETWEEN 31 AND 36
THEN 36
ELSE ''
END AS MONTH
However I need to get it so that it auto groups so that it takes in account future months (42, 48, 54, 60....) but I need to be able to do this in the SSRS query window and havent been able to find a way of getting it to work.
If you need to group by every 12th, then doing an integer division of 12 on the month subtracted by 1, will give you the interval they belong to.
You can then group by that interval.
For example:
Month 1 will be (1-1) / 12 = 0 and this will be your first interval
Month 2 will be (2-1) / 12 = 0 Still first interval
Month 13 will be (13 - 1) / 12 = 1 The beginning of second interval
Month 36 will be (36 -1) / 12 = 2 The beginning of third interval
And so forth? That way you do not have to case indefinitely.

mysql Return amount of order for hour with on colum day of month

I have a mysql db which I use to return amounts of orders by hour in a specific day. I use this SELECT statement for that.
select
hour(datains),sum(valore)
from
ordini
where (stato=10 or stato = 1 ) and DATE(datains) = DATE_SUB(CONCAT(CURDATE(), ' 00:00:00'), INTERVAL 0 DAY)
group by hour(datains)
order by
id DESC
It returns:
+--------------+---------------+
| hour datains | valore |
| 12 | 34 |
| 11 | 56 |
| 10 | 134 |
+-------------------------------
Now I need to have columns for a certain number of days, like this.
+--------------+---------------+--------------+--------------+
| hour datains | 01-01-2014 | 02-01-2014 | 03-01-2014 |
| 12 | 34 | 34 | 77 |
| 11 | 56 | 0 | 128 |
| 10 | 134 | 66 | 12 |
+------------------------------+-----------------------------+
Is this possible?
It seems you have a table ordini with columns datains, valore, and stato.
Perhaps you can try this query to generate hour-by-hour aggregates for a three days' worth of recent sales, but not including today.
SELECT DATE_FORMAT(datains, '%Y-%m-%d %H:00') AS hour,
SUM(valore) AS valore
FROM ordini
WHERE (stato = 1 OR stato = 10)
AND datains >= CURRENT_DATE() - INTERVAL 3 DAY
AND datains < CURRENT_DATE
GROUP BY DATE_FORMAT(datains, '%Y-%m-%d %H:00')
ORDER BY DATE_FORMAT(datains, '%Y-%m-%d %H:00')
This will give you a result set with one row for each hour of the three days, for example:
2014-01-01 10:00 456
2014-01-01 11:00 123
2014-01-02 10:00 28
2014-01-02 11:00 350
2014-01-02 12:00 100
2014-01-02 13:00 17
2014-01-03 10:00 321
2014-01-03 11:00 432
2014-01-03 12:00 88
2014-01-03 13:00 12
That's the data summary you have requested, but formatted row-by-row. Your next step is to figure out an appropriate technique to pivot that result set, formatting it so some rows become columns.
It happens that I have just written a post on this very topic. It is here:
http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/