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.
Related
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
I have a table where the count of a specific data goes up to 5 and then rolls over to 0, I would like to query the table which shows the actual count as shown below
Desired OutPut:
Dev_count
Actual_Count
1
1
2
2
3
3
4
4
5
5
0
6
1
7
2
8
3
9
4
10
5
11
0
12
I tried using a Trigger to update an additional column with actual count using below SQL script
CREATE TRIGGER insert_continuous_count BEFORE INSERT ON x_table
FOR EACH ROW SET
NEW.continuous_count = (SELECT continuous_count
FROM x_table
where device_id = NEW.device_id
order by No DESC LIMIT 1
) + 1;
Then I read somewhere that the trigger cannot update the same table which is already being used (for reading or writing) by the statement that invoked the function or trigger.
Is there any easier way to get the desired output?
I think you need something like this :
select dev_count,
#row_number:= #row_number + 1 as Actual_Count
from test_tbl
cross join (select #row_number := 0) x;
Demo: https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/139
In MySQL 8+ you can use ROW_NUMBER function:
SELECT
dev_count,
ROW_NUMBER() OVER () as rn
FROM test_tbl
ORDER BY rn;
Demo: https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/144
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.
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
I have a table in the following format:
cId seq
--- ---
A 1
A 2
A 4
A 5
B 8
B 9
A 12
A 13
I would like to write a query that would produce another table that looks like:
cId seq consecutive
--- --- -----------
A 1 1
A 2 1
A 4 2
A 5 2
B 8 3
B 9 3
A 12 4
A 13 4
What I am trying to do is identify consecutive seq values that have the same cId and then number them.
I was thinking of using Lag function to determine the previous seq value and then setting the consecutive column but don't know how to increment the value when I encounter the next break.
SELECT [cId],
[Seq],
CASE WHEN [Seq] - 1 = LAG([Seq], 1, [Seq]) OVER ( ORDER BY [Seq]) THEN 1
ELSE 2 END as consecutive
FROM #ConsecutiveData
This query will put a 2 next to the start of each sequence. That's the closest I have come.
I think author is not using MySQL, since, as far as I know, there is no LAG function in MySQL.
Below is a possible solution for MSSQL:
SELECT
cid,
seq,
DENSE_RANK() OVER (ORDER BY seq - row_num) consecutive
FROM (
SELECT
cid,
seq,
ROW_NUMBER() OVER (ORDER BY seq) row_num
FROM
test_table
) data
;
Check at SQLFiddle: SQLFiddle Example