How to select MAX/MIN in MySQL with dynamic between clause - mysql

Assume a table with two columns t (a string with TimeStamps) and v (decimal). For each t I want to query the MAXIMUM of the value v in a certain range defined by the current t.
How can i transfer below statement to proper SQL?
select t, max(v for t between t-2MIN and t+2min) from table_name;
Example:
Assume below table.
t
v
1
3
2
2
3
5
4
4
5
8
6
1
I need an SQL-statement which gives me (for e.g. a width 2: max(v for t between t-2 and t+2)) the following result
t
v
1
5
2
5
3
8
4
8
5
8
6
8

Join the table with itself using the range as the joining condition.
SELECT t1.t, MAX(t2.v) AS max_v
FROM table_name AS t1
JOIN table_name AS t2 ON t2.t BETWEEN t1.t - 2 AND t1.t + 2
GROUP BY t1.t
If you use MySQL 8.x I think you should be able to do it using window functions, but I don't know the proper syntax for this.

In MySql 8 you can use a MAX OVER with rows between a range.
select t
, max(v) over (order by t rows
between 2 preceding and 2 following) v
from table_name

Related

Extracting rows with a consecutive pattern that exceeds a threshold

I currently have this set of data.
Id
pattern
1
1
2
2
3
1
4
2
5
3
6
4
7
1
8
2
9
1
10
2
11
3
I have ids sorted ascending, and a column called pattern. The goal is to retrieve only the rows with a consecutive pattern >=3 down the table.
So the result would be:
Id
pattern
3
1
4
2
5
3
6
4
9
1
10
2
11
3
Since the pattern for Ids 3-6 have consecutively reached >=3, we will return these 4 rows.
Same goes for Ids 9-11.
Id 1-2 did not reach the threshold of 3. Same for Id 7-8.
Would appreciate any help!
Use SUM() window function to create the groups of the sequences and with MAX() window function check the max pattern in each group:
SELECT Id, pattern
FROM (
SELECT *, MAX(pattern) OVER (PARTITION BY grp) max_pattern
FROM (
SELECT *, SUM(pattern = 1) OVER (ORDER BY Id) grp
FROM tablename
) t
) t
WHERE max_pattern >= 3;
Or, with a correlated subquery, for versions of MySql that do not support window functions:
SELECT t1.*
FROM tablename t1
WHERE (SELECT t2.pattern FROM tablename t2 WHERE t2.Id = t1.Id + (3 - t1.pattern)) = 3;
See the demo.

Create histogram given start and end values in SQL

I have an SQL table with "start" and "end" columns: for the sake of simplicity, let's assume they are integers between 1 and 10. I would like to somehow obtain a histogram of the values between "start" and "end".
For instance, given the following rows:
start
end
3
8
4
9
I would like to obtain the following histogram:
time
count
1
0
2
0
3
1
4
2
5
2
6
2
7
2
8
2
9
1
10
0
I really have no idea where to start looking in the SQL syntax to get that result -- maybe an inner join?
You can use a recursive CTE to generate times -- if you don't have a handy tally or numbers table. Then join and aggregate:
with recursive cte as (
select 1 as t
union all
select t + 1
from cte
where t < 10
)
select cte.t,
(select count(*)
from t
where cte.t between t.start and t.end
) as cnt
from cte;
Here is a db<>fiddle.

Compare 2 views with different number of columns

I have 2 views with different number of columns. 1 of the views has been joined with another view that is why it has additional columns.
The first view has 113 records (View 2), while the updated view (View 1) has 130 columns. I would like to find out the number of records that are extra in View 1
.
View 1 View 2
A|B|C|D|E A|B|C
1 2 3 4 5 1 2 3
1 2 3 7 8
3 2 1 4 5 3 2 1
3 2 1 7 8
expected result :
1 2 3 7 8
3 2 1 7 8
Thanks.
You can get that extra records by using 'not in' or 'not exists' conditions
select * from view1 m where not exists (
select 1 from view2 u where (m.a=u.a and m.b=u.b and m.c=u.c)
You can change those conditions as per your requirement
With left join also will get the required result
select m.* from view1 m left join view2 u
(m.a=u.a and m.b=u.b and m.c=u.c)
where u.a is null and u.b is null and u.c is null
You shoul probably refactor your DB schema and data logic.
But just to resolve your weird requirements you can:
http://sqlfiddle.com/#!9/cf2c50/2
SELECT t.a, t.b, t.c, t.d, t.e
FROM (
SELECT v1.*, IF(#idx = concat(v1.a,v1.b,v1.c),1,0) `filter`,#idx := concat(v1.a,v1.b,v1.c)
FROM v1
INNER JOIN v2
ON v1.a=v2.a AND v1.b=v2.b AND v1.c=v2.c
ORDER BY v1.a,v1.b,v1.c
) t
WHERE t.`filter`=1;
It is not best example of query performance, but it should return expected result.

Is somehow possible to create select a series in mysql?

Is possible to select a numerical series or date series in SQL? Like create a table with N rows like 1 to 10:
1
2
3
...
10
or
2010-01-01
2010-02-01
...
2010-12-01
If you install common_schema, you can use the numbers table to easily create queries to output those types of ranges.
For example, these 2 queries will produce the output from your examples:
select n
from common_schema.numbers
where n between 1 and 10
order by n
select ('2010-01-01' + interval n month)
from common_schema.numbers
where n between 0 and 11
order by n
An SQL solution:
SELECT *
FROM (
SELECT 1 as id
UNION SELECT 2
UNION SELECT 3
UNION SELECT 4
UNION SELECT 5
)
Yep! Both MySQL and Microsoft SQL Server (and others) have a BETWEEN operator. I don't remember off the top of my head if it's inclusive or exclusive, but here's a starting point!
http://www.w3schools.com/sql/sql_between.asp

Sorting a column and setting the result to another column in MySql

I have a problem about a query. Let's say I have a table structure like this.
TABLE_A
Id - Standing - Point
1 null 8
2 null 9
3 null 12
4 null 11
5 null 4
When I sort this table by Point column(SELECT * FROM TABLE_A ORDER BY Point DESC), I want to update Standing column to be updated according to sort results. After sorting and setting these values to Standing column, the result that I want to have is this:
TABLE_A
Id - Standing - Point
1 4 8
2 3 9
3 1 12
4 2 11
5 5 4
Is it possible to do this? If yes, how?
Thanks in advance...
You can do this with the rather arcane syntax:
update table_A
set standing = (select cnt
from (select count(*) as cnt
from table_a a2
where a2.point >= table_A.point
)
)
The use of the nested select is simply a syntax convention required in MySQL.