patternsqlMinor
LIMIT of rows but with complete "sets"
Viewed 0 times
rowswithlimitbutcompletesets
Problem
I guess this is a pretty tough one. I want to get results from the database, per 5 rows max (so a limit of 5 each time), but each time I don't want to return incomplete "sets" either. Look at my table of forms:
So I want to return my results in sets of 5 database rows BUT with complete forms. In this case I will have incomplete results, cause I don't have all rows of form with ID
Anyone who has any idea how to accomplish this?
At the moment my query looks, more or less, like this:
(this is just an example so no worries about the sql injection vulnerability ;)). As you can see I check for the last returned row id and created column every time I run a new query, so I know where I ended. But like I said, this will return a complete form
+----+--------+------------+
| id | formID | created |
+----+--------+------------+
| 1 | 111111 | 2014-01-01 |
+----+--------+------------+
| 2 | 111111 | 2014-01-01 |
+----+--------+------------+
| 3 | 111111 | 2014-01-01 |
+----+--------+------------+
| 4 | 222222 | 2014-01-01 |
+----+--------+------------+
| 5 | 222222 | 2014-01-01 |
+----+--------+------------+
| 6 | 222222 | 2014-01-01 |
+----+--------+------------+
| 7 | 333333 | 2014-01-02 |
+----+--------+------------+So I want to return my results in sets of 5 database rows BUT with complete forms. In this case I will have incomplete results, cause I don't have all rows of form with ID
222222 returned. So either I need to get 3 results (less than 5 but complete forms) or 6 (a bit more than 5 but also complete forms). Anyone who has any idea how to accomplish this?
At the moment my query looks, more or less, like this:
SELECT `id`, `formId`, `created`
FROM `forms`
WHERE created >= $lastCreated
AND id != $lastId
ORDER BY created
LIMIT 5;(this is just an example so no worries about the sql injection vulnerability ;)). As you can see I check for the last returned row id and created column every time I run a new query, so I know where I ended. But like I said, this will return a complete form
111111 but an incomplete form 222222.Solution
What you want is called
Here is one way to do this. The details will differ, depending on what you want the
This will return 6 rows in your example case. If you replace
In order to try and adapt that to your specific case more closely, you can add the
This Rextester demo shows how it works both with
I am not sure about the
TOP WITH TIES in SQL Server and FETCH FIRST .. WITH TIES in standard SQL. The MySQL LIMIT clause is equivalent to TOP (and FETCH FIRST) but it doesn't have WITH TIES functionality.Here is one way to do this. The details will differ, depending on what you want the
ORDER BY to be based on. I used formID:SELECT f.*
FROM forms AS f
INNER JOIN
( SELECT formID
FROM forms
ORDER BY formID
LIMIT 1 OFFSET 4 -- offset 5 minus 1
) AS fm
ON f.formID <= fm.formID
ORDER BY f.formID ;This will return 6 rows in your example case. If you replace
<= with < it will return 3 rows.In order to try and adapt that to your specific case more closely, you can add the
created column to the "equation":SELECT f.*
FROM forms AS f
INNER JOIN
( SELECT created, formID
FROM forms
WHERE created >= '2014-01-01'
ORDER BY created, formID
LIMIT 1 OFFSET 4
) AS fm
ON (f.created, f.formID) = '2014-01-01' ;This Rextester demo shows how it works both with
<= and with <.I am not sure about the
id != $lastId predicate in your query, but if it is an actual part of the filter rather than just your attempt at resolving the issue in question, then you will probably need to add it to the above query as well, both to the main WHERE and to the nested WHERE.Code Snippets
SELECT f.*
FROM forms AS f
INNER JOIN
( SELECT formID
FROM forms
ORDER BY formID
LIMIT 1 OFFSET 4 -- offset 5 minus 1
) AS fm
ON f.formID <= fm.formID
ORDER BY f.formID ;SELECT f.*
FROM forms AS f
INNER JOIN
( SELECT created, formID
FROM forms
WHERE created >= '2014-01-01'
ORDER BY created, formID
LIMIT 1 OFFSET 4
) AS fm
ON (f.created, f.formID) <= (fm.created, fm.formID)
WHERE f.created >= '2014-01-01' ;Context
StackExchange Database Administrators Q#159928, answer score: 4
Revisions (0)
No revisions yet.