MySQL Group by consecutive values and count - mysql

I have a table that looks like this
id
1
2
4
5
6
10
11
So a bunch of consecutive values, an unknown number of absent fields and then other consecutive values.
What I am trying to achieve is to get
id
stint
1
0
2
0
4
1
5
1
6
1
10
2
11
2
By incrementing every time the number of the stint, which I can later use for summing over other columns.
Is it possible? Thanks

If your MySQL version support window function.
You can try to use LAG window function in subquery to get previous id column, then use SUM condition aggregate window function.
Query #1
SELECT Id,
SUM(id - n_Id > 1) OVER(ORDER BY id) stint
FROM (
SELECT *,LAG(id,1,id) OVER(ORDER BY id) n_Id
FROM T
) t1
Id
stint
1
0
2
0
4
1
5
1
6
1
10
2
11
2
View on DB Fiddle

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.

How to select X consecutive numbers of rows meeting a condition

I the following table:
ID TIMESLOT_ID SLOTS_AVAILABLE
1 1 10
2 3 2
3 8 3
4 9 10
5 2 10
6 6 10
7 4 10
I want to perform a query where I can get all rows where SLOTS_AVAILABLE is equal or greater than (user_input_1) AND the next (user_input_2) consecutive rows following to that one meet the same condition (SLOTS_AVAILABLE is equal or greater than (user_input_1))
So if (user_input_1) is 3 and (user_input_2) is 3 the result would be:
ID TIMESLOT_ID SLOTS_AVAILABLE
3 8 3
4 9 10
Hmmm . . . If I understand correctly, you want window functions:
select t.*
from (select t.*,
sum(case when slots_available >= :user_input_1 then 1 else 0 end) over
(order by id
rows between current row and :user_input_2 following
) as cnt
from t
) t
where cnt = :user_input_2 + 1;
This requires MySQL 8+.
Here is a db<>fiddle.

SQL - Max value from a group by when creating a new field

I have a database with a table called BOOKINGS containing the following values
main-id place-id start-date end-date
1 1 2018-8-1 2018-8-8
2 2 2018-6-6 2018-6-9
3 3 2018-5-5 2018-5-8
4 4 2018-4-4 2018-4-5
5 5 2018-3-3 2018-3-10
5 1 2018-1-1 2018-1-6
4 2 2018-2-1 2018-2-10
3 3 2018-3-1 2018-3-28
2 4 2018-4-1 2018-4-6
1 5 2018-5-1 2018-5-15
1 3 2018-6-1 2018-8-8
1 4 2018-7-1 2018-7-6
1 1 2018-8-1 2018-8-18
1 2 2018-9-1 2018-9-3
1 5 2018-10-1 2018-10-6
2 5 2018-11-1 2018-11-5
2 3 2018-12-1 2018-12-25
2 2 2018-2-2 2018-2-19
2 4 2018-4-4 2018-4-9
2 1 2018-5-5 2018-5-23
What I need to do is for each main-id I need to find the largest total number of days for every place-id. Basically, I need to determine where each main-id has spend the most time.
This information must then be put into a view, so unfortunately I can't use temporary tables.
The query that gets me the closest is
CREATE VIEW `MOSTTIME` (`main-id`,`place-id`,`total`) AS
SELECT `BOOKINGS`.`main-id`, `BOOKINGS`.`place-id`, SUM(DATEDIFF(`end-date`, `begin-date`)) AS `total`
FROM `BOOKINGS`
GROUP BY `BOOKINGS`.`main-id`,`RESERVATION`.`place-id`
Which yields:
main-id place-id total
1 1 24
1 2 18
1 5 5
2 1 2
2 2 20
2 4 9
3 1 68
3 2 24
3 3 30
4 1 5
4 2 10
4 4 1
5 1 19
5 2 4
5 5 7
What I need is then the max total for each distinct main-id:
main-id place-id total
1 1 24
2 2 20
3 1 68
4 2 10
5 1 19
I've dug through a large amount of similar posts that recommend things like self joins; however, due to the fact that I have to create the new field total using an aggregate function (SUM) and another function (DATEDIFF) rather than just querying an existing field, my attempts at implementing those solutions have been unsuccessful.
I am hoping that my query that got me close will only require a small modification to get the correct solution.
Having hyphen character - in column name (which is also minus operator) is a really bad idea. Do consider replacing it with underscore character _.
One possible way is to use Derived Tables. One Derived Table is used to determine the total on a group of main id and place id. Another Derived Table is used to get maximum value out of them based on main id. We can then join back to get only the row corresponding to the maximum value.
CREATE VIEW `MOSTTIME` (`main-id`,`place-id`,`total`) AS
SELECT b1.main_id, b1.place_id, b1.total
FROM
(
SELECT `main-id` AS main_id,
`place-id` AS place_id,
SUM(DATEDIFF(`end-date`, `begin-date`)) AS total
FROM BOOKINGS
GROUP BY main_id, place_id
) AS b1
JOIN
(
SELECT dt.main_id, MAX(dt.total) AS max_total
FROM
(
SELECT `main-id` AS main_id,
`place-id` AS place_id,
SUM(DATEDIFF(`end-date`, `begin-date`)) AS total
FROM BOOKINGS
GROUP BY main_id, place_id
) AS dt
GROUP BY dt.main_id
) AS b2
ON b1.main_id = b2.main_id AND
b1.total = b2.max_total
MySQL 8+ solution would be utilizing the Row_Number() functionality:
CREATE VIEW `MOSTTIME` (`main-id`,`place-id`,`total`) AS
SELECT b.main_id, b.place_id, b.total
FROM
(
SELECT dt.main_id,
dt.place_id,
dt.total
ROW_NUMBER() OVER (PARTITION BY dt.main_id
ORDER BY dt.total DESC) AS row_num
FROM
(
SELECT `main-id` AS main_id,
`place-id` AS place_id,
SUM(DATEDIFF(`end-date`, `begin-date`)) AS total
FROM BOOKINGS
GROUP BY main_id, place_id
) AS dt
GROUP BY dt.main_id
) AS b
WHERE b.row_num = 1

Access Totals Query Not Necessarily Returning First Record

I have a table of data like this:
id user_id A B C
=====================
1 15 1 2 3
2 15 1 2 5
3 20 1 3 9
4 20 1 3 7
I need to remove duplicate user ids and keep the record that sorts lowest when sorting by A then B then C. So using the above table, I set up a temp query (qry_temp) that simply does the sort--first on user_id, then on A, then on B, then on C. It returns the following:
id user_id A B C
====================
1 15 1 2 3
2 15 1 2 5
4 20 1 3 7
3 20 1 3 9
Then I wrote a Totals Query based on qry_temp that just had user_id (Group By) and then id (First), and I assumed this would return the following:
user_id id
===========
15 1
20 4
But it doesn't seem to do that--instead it appears to be just returning the lowest id in a group of duplicate user ids (so I get 1 and 3 instead of 1 and 4). Shouldn't the Totals query use the order of the query it's based upon? Is there a property setting in the query that might impact this or another way to get what I need? If it helps, here is the SQL:
SELECT qry_temp.user_id, First(qry_temp.ID) AS FirstOfID
FROM qry_temp
GROUP BY qry_temp.user_id;
You need a different type of query, for example:
SELECT tmp.id,
tmp.user_id,
tmp.a,
tmp.b,
tmp.c
FROM tmp
WHERE (( ( tmp.id ) IN (SELECT TOP 1 id
FROM tmp t
WHERE t.user_id = tmp.user_id
ORDER BY t.a,
t.b,
t.c,
t.id) ));
Where tmp is the name of your table. First, Last, Min and Max are not dependent on a sort order. In relational databases, sort orders are quite ephemeral.

How can I get the max value within a max value in mysql?

I have a schema like the following
id (INT)
Cycle_Number (INT)
Cycle_Day (INT)
Date (date)
...other columns irrelevant to the question...
How can I get the row that has the max Cycle_Day within the max Cycle_Number
For example, say I have the following data
ID Cycle_Number Cycle_Day Date
1 1 1 2011-12-01
2 1 2 2011-12-02
3 2 1 2011-12-03
4 2 2 2011-12-04
5 2 3 2011-12-05
6 2 4 2011-12-06
7 3 1 2011-12-07
8 3 2 2011-12-08
9 3 3 2011-12-09
The query would return row 9. (It has the highest Cycle_Day within the highest Cycle_Number)
Thanks
this one is compatible MySql 5.5 with no joint tables
SELECT id
FROM cycles
ORDER BY Cycle_Number DESC , Cycle_Day DESC
LIMIT 0 , 1
Regards
This SQL query should provide the max value you want.
SELECT ID, Cycle_Number, Cycle_Day, Date
FROM yourTable AS t
CROSS JOIN (
SELECT MAX(Cycle_Number) AS Cycle_Number FROM yourTable
) AS sq USING (Cycle_Number)
ORDER BY Cycle_Day DESC LIMIT 1