mysql: select between - mysql

I am getting invalid use of group function, not really sure where the problem is
expected result is list of timestamps from within xxx seconds starting from the max available
Please advise.
SELECT timestamp, response_time
FROM results
WHERE id = XYZ AND timestamp between
(SELECT MAX(timestamp) FROM results inn WHERE id = 22) AND
(SELECT timestamp FROM results WHERE id =22 AND timestamp = MAX(timestamp) - XXX)
ORDER BY timestamp DESC
thank you

SELECT timestamp, response_time
FROM results
WHERE id = #xyz
AND timestamp BETWEEN
(
SELECT MAX(timestamp)
FROM results
WHERE id = 22
) AND
(
SELECT MAX(timestamp)
FROM results
WHERE id = 22
) - #xxx
ORDER BY
timestamp DESC
Make sure you have an index on (id, timestamp) for this to work fast.

Related

How do I select data going back a period of time for each group?

I want for each group id to get the latest week's worth of data. Not from a specific date, but counting backwards from the MAX(startTime) of each individual group.
However, the following does not seem to work. I assume it's because startTime in each group (a single value) is BETWEENed by itself? Otherwise, how do I keep it in my filter?
SELECT
id
, startTime
FROM MyTable
GROUP BY id, startTime
HAVING startTime BETWEEN MAX(startTime) - INTERVAL 1 WEEK AND MAX(startTime)
What's the right query?
Also, in my case it has to work with MySQL 5.7.
SELECT m.id, m.startTime
FROM (
SELECT id, MAX(startTime) AS startTime
FROM MyTable GROUP BY id
) AS x
JOIN MyTable AS m ON m.id = x.id
AND m.startTime BETWEEN x.startTime - INTERVAL 1 WEEK AND x.startTime;

MySQL - get min/max of consecutive events in a series of rows

I have a table that looks like this:
http://sqlfiddle.com/#!9/152d2/1/0
CREATE TABLE Table1 (
id int,
value decimal(10,5),
dt datetime,
threshold_id int
);
Current Query:
SELECT sensors_id, DATE_FORMAT(datetime, '%Y-%m-%d'), MIN(value), MAX(value)
FROM Readings
WHERE datetime < "2015-11-18 00:00:00"
AND datetime > "2015-10-18 00:00:00"
AND sensors_id = 9
GROUP BY DATE_FORMAT(datetime, '%Y-%m-%d')
ORDER BY datetime DESC
What I'm trying to do is to return the min/max value in each group, where threshold_id IS NOT NULL. Therefore, the example should return something like:
min_value | max_value | start_date | end_date
9 | 10.5 | 2015-07-29 10:52:31 | 2015-07-29 10:57:31
8.5 | 9.5 | 2015-07-29 11:03:31 | 2015-07-29 11:05:31
I can't work out how to do this grouping. I need to return the min/max for each group of consecutive rows where the threshold_id IS NOT NULL.
Use user variables to compare existing value to the previous value and increment a column you can use to group by,tested on my machine.
SELECT MIN(value),MAX(value),MIN(dt),MAX(dt)
FROM (
SELECT id,value,dt,
CASE WHEN COALESCE(threshold_id,'')=#last_ci THEN #n ELSE #n:=#n+1 END AS g,
#last_ci := COALESCE(threshold_id,'') As th
FROM
Table1, (SELECT #n:=0) r
ORDER BY
id
) s
WHERE th!=''
GROUP BY
g
For mysql 8 this could be rewritten as below.Use a CTE to get different sequences and GROUP By the difference between them.
WITH cte as (
SELECT *,
ROW_NUMBER() OVER (ORDER BY id)as rn,
ROW_NUMBER() OVER (PARTITION BY threshold_id ORDER BY id)as rnn
FROM Table1
ORDER BY id
)
SELECT MIN(value),MAX(value),MIN(dt),MAX(dt) FROM cte WHERE threshold_id IS NOT NULL GROUP BY rn-rnn
MYSQL8
FIDDLE
Your sample data only includes a single day's worth, so you only get a single row back (assuming you want to group by day):
SELECT DAYOFYEAR(dt) `day`, MIN(`value`) min_value, MAX(`value`) max_value
FROM Table1
GROUP BY `day`
ORDER BY `day` ASC

How to Group a table and get results for a row based on the previous rows' data

I have a lookup table that relates dates and people associated with those dates:
id, user_id,date
1,1,2014-11-01
2,2,2014-11-01
3,1,2014-11-02
4,3,2014-11-02
5,1,2014-11-03
I can group these by date(day):
SELECT DATE_FORMAT(
MIN(date),
'%Y/%m/%d 00:00:00 GMT-0'
) AS date,
COUNT(*) as count
FROM user_x_date
GROUP BY ROUND(UNIX_TIMESTAMP(created_at) / 43200)
But, how can get the number of unique users, that have now shown up previously? For instance this would be a valid result:
unique, non-unique, date
2,0,2014-11-01
1,1,2014-11-02
0,1,2014-11-03
Is this possibly without having to rely on a scripting language to keep track of this data?
I think this query will do what you want, at least it seems to work for your limited sample data.
The idea is to use a correlated sub-query to check if the user_id has occurred on a date before the date of the current row and then do some basic arithmetic to determine number of unique/non-unique users for each date.
Please give it a try.
select
sum(u) - sum(n) as "unique",
sum(n) as "non-unique",
date
from (
select
date,
count(user_id) u,
case when exists (
select 1
from Table1 i
where i.user_id = o.user_id
and i.date < o.date
) then 1 else 0
end n
from Table1 o
group by date, user_id
) q
group by date
order by date;
Sample SQL Fiddle
I didn't include the id column in the sample fiddle as it's not needed (or used) to produce the result and won't change anything.
This is the relevant question: "But, how can get the number of unique users, that have now shown up previously?"
Calculate the first time a person shows up, and then use that for the aggregation:
SELECT date, count(*) as FirstVisit
FROM (SELECT user_id, MIN(date) as date
FROM user_x_date
GROUP BY user_id
) x
GROUP BY date;
I would then use this as a subquery for another aggregation:
SELECT v.date, v.NumVisits, COALESCE(fv.FirstVisit, 0) as NumFirstVisit
FROM (SELECT date, count(*) as NumVisits
FROM user_x_date
GROUP BY date
) v LEFT JOIN
(SELECT date, count(*) as FirstVisit
FROM (SELECT user_id, MIN(date) as date
FROM user_x_date
GROUP BY user_id
) x
GROUP BY date
) fv
ON v.date = fv.date;

Mysql Union Query Record result emptys column

I have a union query to get a Max date record from two tables
SELECT
id,
MAX(mx) AS max_date,
`assigned_user_id`
FROM (SELECT
id,
MAX(date_due) AS mx,
`assigned_user_id`
FROM tasks
WHERE `deleted` = 0
AND `parent_id` = 'aa6f0330-7a17-572f-94b5-4a5db1a1201f'
AND `parent_type` = 'Accounts'
AND date_due >= CURDATE() UNION SELECT
id,
MAX(date_start) AS mx,
`assigned_user_id`
FROM calls
WHERE `deleted` = 0
AND `account_id` = 'aa6f0330-7a17-572f-94b5-4a5db1a1201f'
AND date_start >= CURDATE()) s
this would look into both calls and Tasks and get me the Futuristic Call or a Task, but when i run this and i have a Futuristic Call and task is older, i get NULL in id and assigned_user_id columns. How do i fetch the whole info for the MAX date record.
When i Run individual Queries, i get null for first one while a record in the second one.
Perhaps I'm misreading the problem, or I'm missing something - in which case, write me a comment to let me know, and I can delete this post altogether.
But, the way I understand what you've written, you want to:
Get the single record in tasks with the given parent_id and parent_type and where date_due >= CURDATE() which has the latest date_due value.
Get that same type of record from the calls table (using date_start instead of date_due).
Of those two records, find the one record with the later date value. Select the id, the date (as max_date), and the assigned_user_id from that record.
Your query (and sub-queries) could just order by descending date and fetch only the first record.
I'm thinking something like this...
SELECT id,
mx AS max_date,
`assigned_user_id`
FROM (
SELECT id,
date_due as mx,
`assigned_user_id`
FROM tasks
WHERE `deleted` = 0
AND `parent_id` = 'aa6f0330-7a17-572f-94b5-4a5db1a1201f'
AND `parent_type` = 'Accounts'
AND date_due >= CURDATE()
ORDER BY date_due DESC
LIMIT 1
UNION
SELECT id,
date_start as mx,
`assigned_user_id`
FROM calls
WHERE `deleted` = 0
AND `account_id` = 'aa6f0330-7a17-572f-94b5-4a5db1a1201f'
AND date_start >= CURDATE()
ORDER BY date_start DESC
LIMIT 1
)
ORDER BY max_date DESC
LIMIT 1
Use UNION ALL. To allow duplicate values, use the ALL keyword with UNION.
Select Max(max_date) from
(SELECT
id,
MAX(mx) AS max_date,
assigned_user_id
FROM
(SELECT
id,
MAX(date_due) AS mx,
assigned_user_id
FROM tasks
WHERE deleted = 0
AND parent_id = 'aa6f0330-7a17-572f-94b5-4a5db1a1201f'
AND parent_type = 'Accounts'
AND date_due >= CURDATE() group by id UNION SELECT
id,
MAX(date_start) AS mx,
assigned_user_id
FROM calls
WHERE deleted = 0
AND account_id = 'aa6f0330-7a17-572f-94b5-4a5db1a1201f'
AND date_start >= CURDATE()) s group by id)
as temp

MySQL - How to select rows with the min(timestamp) per hour of a given date

I have a table of production readings and need to get a result set containing a row for the min(timestamp) for EACH hour.
The column layout is quite simple:
ID,TIMESTAMP,SOURCE_ID,SOURCE_VALUE
The data sample would look like:
123,'2013-03-01 06:05:24',PMPROD,12345678.99
124,'2013-03-01 06:15:17',PMPROD,88888888.99
125,'2013-03-01 06:25:24',PMPROD,33333333.33
126,'2013-03-01 06:38:14',PMPROD,44444444.44
127,'2013-03-01 07:12:04',PMPROD,55555555.55
128,'2013-03-01 10:38:14',PMPROD,44444444.44
129,'2013-03-01 10:56:14',PMPROD,22222222.22
130,'2013-03-01 15:28:02',PMPROD,66666666.66
Records are added to this table throughout the day and the source_value is already calculated, so no sum is needed.
I can't figure out how to get a row for the min(timestamp) for each hour of the current_date.
select *
from source_readings
use index(ID_And_Time)
where source_id = 'PMPROD'
and date(timestamp)=CURRENT_DATE
and timestamp =
( select min(timestamp)
from source_readings use index(ID_And_Time)
where source_id = 'PMPROD'
)
The above code, of course, gives me one record. I need one record for the min(hour(timestamp)) of the current_date.
My result set should contain the rows for IDs: 123,127,128,130. I've played with it for hours. Who can be my hero? :)
Try below:
SELECT * FROM source_readings
JOIN
(
SELECT ID, DATE_FORMAT(timestamp, '%Y-%m-%d %H') as current_hour,MIN(timestamp)
FROM source_readings
WHERE source_id = 'PMPROD'
GROUP BY current_hour
) As reading_min
ON source_readings.ID = reading_min.ID
SELECT a.*
FROM Table1 a
INNER JOIN
(
SELECT DATE(TIMESTAMP) date,
HOUR(TIMESTAMP) hour,
MIN(TIMESTAMP) min_date
FROM Table1
GROUP BY DATE(TIMESTAMP), HOUR(TIMESTAMP)
) b ON DATE(a.TIMESTAMP) = b.date AND
HOUR(a.TIMESTAMP) = b.hour AND
a.timestamp = b.min_date
SQLFiddle Demo
With window function:
WITH ranked (
SELECT *, ROW_NUMBER() OVER(PARTITION BY HOUR(timestamp) ORDER BY timestamp) rn
FROM source_readings -- original table
WHERE date(timestamp)=CURRENT_DATE AND source_id = 'PMPROD' -- your custom filter
)
SELECT * -- this will contain `rn` column. you can select only necessary columns
FROM ranked
WHERE rn=1
I haven't tested it, but the basic idea is:
1) ROW_NUMBER() OVER(PARTITION BY HOUR(timestamp) ORDER BY timestamp)
This will give each row a number, starting from 1 for each hour, increasing by timestamp. The result might look like:
|rest of columns |rn
123,'2013-03-01 06:05:24',PMPROD,12345678.99,1
124,'2013-03-01 06:15:17',PMPROD,88888888.99,2
125,'2013-03-01 06:25:24',PMPROD,33333333.33,3
126,'2013-03-01 06:38:14',PMPROD,44444444.44,4
127,'2013-03-01 07:12:04',PMPROD,55555555.55,1
128,'2013-03-01 10:38:14',PMPROD,44444444.44,1
129,'2013-03-01 10:56:14',PMPROD,22222222.22,2
130,'2013-03-01 15:28:02',PMPROD,66666666.66,1
2) Then on the main query we select only rows with rn=1, in other words, rows that has lowest timestamp in each hourly partition (1st row after sorted by timestamp in each hour).