This is a gaps-and-islands problem. Assuming there are no gaps or duplicates in the same id_set
set:
WITH partitioned AS (
SELECT
*,
number - ROW_NUMBER() OVER (PARTITION BY id_set) AS grp
FROM atable
WHERE status = 'FREE'
),
counted AS (
SELECT
*,
COUNT(*) OVER (PARTITION BY id_set, grp) AS cnt
FROM partitioned
)
SELECT
id_set,
number
FROM counted
WHERE cnt >= 3
;
Here's a SQL Fiddle demo* link for this query: http://sqlfiddle.com/#!1/a2633/1.
UPDATE
To return only one set, you could add in one more round of ranking:
WITH partitioned AS (
SELECT
*,
number - ROW_NUMBER() OVER (PARTITION BY id_set) AS grp
FROM atable
WHERE status = 'FREE'
),
counted AS (
SELECT
*,
COUNT(*) OVER (PARTITION BY id_set, grp) AS cnt
FROM partitioned
),
ranked AS (
SELECT
*,
RANK() OVER (ORDER BY id_set, grp) AS rnk
FROM counted
WHERE cnt >= 3
)
SELECT
id_set,
number
FROM ranked
WHERE rnk = 1
;
Here's a demo for this one too: http://sqlfiddle.com/#!1/a2633/2.
If you ever need to make it one set per id_set
, change the RANK()
call like this:
RANK() OVER (PARTITION BY id_set ORDER BY grp) AS rnk
Additionally, you could make the query return the smallest matching set (i.e. first try to return the first set of exactly three consecutive numbers if it exists, otherwise four, five etc.), like this:
RANK() OVER (ORDER BY cnt, id_set, grp) AS rnk
or like this (one per id_set
):
RANK() OVER (PARTITION BY id_set ORDER BY cnt, grp) AS rnk
* The SQL Fiddle demos linked in this answer use the 9.1.8 instance as the 9.2.1 one doesn't appear to be working at the moment.
There is no difference in result but there is a bit different semantics.
X [comparison] ALL(set)
mean that set
is empty or the comparison is TRUE
for each entry in the set.
X NOT IN (set)
means that X does not belong to the set.
While [comparison]
is "not equal", both forms are equivalent. But for other comparisons it may be different.
Best Answer
I'm not sure what you mean by "ignoring nulls" here. It returns the number of rows irrespective of any
NULL
sReturns
2
.Altering the above query to
COUNT(C)
would return0
as when usingCOUNT
with an expression other than*
onlyNOT NULL
values of that expression are counted.Suppose the table in your question has the following source data
The query
Returns
Hopefully it is obvious how that result relates to the original data.
Adding that into the
SELECT
list for the previous query producesNotice that the result set has 3 rows and CountOverResult is 3. This is not a coincidence.
The reason for this is because it logically operates on the result set after the
GROUP BY
.COUNT(*) OVER ()
is a windowed aggregate. The absence of anyPARTITION BY
orORDER BY
clause means that the window it operates on is the whole result set.In the case of the query in your question the value of
CountOverResult
is the same as the number of distinctMaritalStatus
values that exist in the base table because there is one row for each of these in the grouped result.