简体   繁体   中英

How to join self join with subquery?

Data:

create table `values` (
     id integer unsigned primary key auto_increment,
     value double,
     `time` time
);

insert into `values` (time, value) values
  ('00:00:01', 1),
  ('00:00:02', 2),
  ('00:00:03', 3),
  ('00:01:01', 4),
  ('00:01:02', 5),
  ('00:01:03', 6);

and fiddle of same http://sqlfiddle.com/#!9/ec3e8/1

SELECT
    vs1.time as t1,
    vs1.value as v1,
    vs2.time as t2,
    vs2.value as v2
FROM `values` vs1, `values` vs2
JOIN (
    SELECT MIN(time) as mint, MAX(time) as maxt FROM `values`
    GROUP BY hour(time), minute(time)
) as te on vs1.time = te.mint AND vs2.time = te.maxt
WHERE vs1.id != vs2.id AND hour(vs1.time) = hour(vs2.time) AND minute(vs1.time) = minute(vs2.time)

I have a timeseries data in mysql. I want to aggreate some statistics from it with one sql query. I'd like group values by time, and then get minimum, maximum, first and last value from group.

I know that mysql doesn't have aggregate functions, ctes, first and last functions, otherwise this would be trivial.

So my plan is to create a product of all rows (join table with itself) and then join it with min and max times of each interval to get first and last value from interval, but this gives error.

Unknown column 'vs1.time' in 'on clause'

What's wrong with my query? And can use the same product of rows to also get minimum and maximum or do I need to join another query with group by ?

Another option would be to make a procedure or so it in some programming language. Procedure is not an option. I'd like to compare performance of raw SQL and doing this in programming language.

This should work on mysql 5.6.

You are mixing the pre-1992 comma-separated join syntax with proper ANSI joins, which you shouldn't. The docs ( https://dev.mysql.com/doc/refman/5.7/en/join.html ) state clearly:

However, the precedence of the comma operator is less than that of INNER JOIN, CROSS JOIN, LEFT JOIN, and so on. If you mix comma joins with the other join types when there is a join condition, an error of the form Unknown column 'col_name' in 'on clause' may occur.

Replacing the comma with CROSS JOIN makes it work: FROM `values` vs1 CROSS JOIN `values` vs2 .

However, I find most of your conditions superfluous. Plus changing the order of joins for readability (especially in order not to pretend to be cross-joining):

SELECT
    vs1.time as t1,
    vs1.value as v1,
    vs2.time as t2,
    vs2.value as v2
FROM 
(
  SELECT MIN(time) as mint, MAX(time) as maxt 
  FROM `values`
  GROUP BY hour(time), minute(time)
) as te
JOIN `values` vs1 ON vs1.time = te.mint
JOIN `values` vs2 ON vs2.time = te.maxt
ORDER BY vs1.time;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM