У меня есть таблица с такими номерами (статус БЕСПЛАТНЫЙ или НАЗНАЧЕН)
Идентификационный номер ----------------------- 1 000001 НАЗНАЧЕН 1 000002 БЕСПЛАТНО 1 000003 НАЗНАЧЕН 1 000004 БЕСПЛАТНО 1 000005 БЕСПЛАТНО 1 000006 НАЗНАЧЕН 1 000007 НАЗНАЧЕН 1 000008 БЕСПЛАТНО 1 000009 БЕСПЛАТНО 1 000010 БЕСПЛАТНО 1 000011 НАЗНАЧЕН 1 000012 НАЗНАЧЕН 1 000013 НАЗНАЧЕН 1 000014 БЕСПЛАТНО 1 000015 НАЗНАЧЕН
и мне нужно найти "n" последовательных чисел, поэтому для n = 3 запрос будет возвращать
1 000008 БЕСПЛАТНО 1 000009 БЕСПЛАТНО 1 000010 БЕСПЛАТНО
Он должен возвращать только первую возможную группу каждого id_set (фактически, он будет выполняться только для id_set для запроса)
Я проверял функции WINDOW, пробовал некоторые запросы вроде COUNT(id_number) OVER (PARTITION BY id_set ROWS UNBOUNDED PRECEDING)
, но это все, что я получил :) Я не мог придумать логики, как это сделать в Postgres.
Я думал о создании виртуального столбца, используя функции WINDOW, считая предыдущие строки для каждого числа, где status = 'FREE', затем выбираю первое число, где count равно моему "n" числу.
Или, может быть, группировать номера по статусу, но только от одного ASSIGNED к другому ASSIGNED и выбирать только группы, содержащие как минимум "n" номеров
РЕДАКТИРОВАТЬ
Я нашел этот запрос (и немного его изменил)
WITH q AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY id_set, status ORDER BY number) AS rnd,
ROW_NUMBER() OVER (PARTITION BY id_set ORDER BY number) AS rn
FROM numbers
)
SELECT id_set,
MIN(number) AS first_number,
MAX(number) AS last_number,
status,
COUNT(number) AS numbers_count
FROM q
GROUP BY id_set,
rnd - rn,
status
ORDER BY
first_number
который производит группы номеров FREE / ASSIGNED, но я хотел бы, чтобы все номера были только из первой группы, которая удовлетворяет условию
id_set
или только один? Пожалуйста, обновите ваш вопрос, если это подразумевалось как его часть с самого начала. (Чтобы другие могли увидеть все требования и предложить свои предложения или обновить свои ответы.)Простой и быстрый вариант:
Требуется последовательная последовательность чисел в
number
(как предусмотрено в вопросе).Работает для любого числа возможных значений,
status
кроме того'FREE'
, даже сNULL
.Главная особенность является вычитать
row_number()
изnumber
после устранения неквалификационных строк. Последовательные числа заканчиваются тем жеgrp
- иgrp
также гарантированно будут в возрастающем порядке .Тогда можно
GROUP BY grp
и посчитать участников. Поскольку вы, кажется, хотите первое вхождение,ORDER BY grp LIMIT 1
вы получаете начальную позицию и длину последовательности (может быть> = n ).Набор строк
Чтобы получить фактический набор чисел, не ищите таблицу в другой раз. Гораздо дешевле с
generate_series()
:Если вы действительно хотите строку с ведущими нулями , как вы показываете в вашем примере значений, используйте
to_char()
сFM
модификатором (режим заполнения):SQL Fiddle с расширенным тестовым набором и обоими запросами.
Тесно связанный ответ:
источник
Это довольно общий способ сделать это.
Имейте в виду, это зависит от того, является ли ваша
number
колонка последовательной. Если это не оконная функция и / или, возможно, потребуется решение типа CTE:источник
M.number-consec+1
(например, для 10 это должно быть10-3+1=8
).number
поля. Хороший вызов по математике, я исправлю это.EXISTS
можно упростить. Поскольку нам нужно только убедиться, что существуют n предыдущих строк, мы можем отброситьAND status = 'FREE'
. И я хотел бы изменить состояние во 2 -EXISTS
кstatus <> 'FREE'
твердеть его от добавленных вариантов в будущем.Это вернет только первое из 3 чисел. Это не требует, чтобы значения
number
были последовательными. Протестировано в SQL-Fiddle :И это покажет все числа (где есть 3 или более последовательных
'FREE'
позиций):источник
В этом случае 5 последовательных чисел - поэтому разница должна быть 4 или другими словами
count(r3.number) = n
иr2.number = r1.number + n - 1
.С присоединениями:
источник
JOIN
синтаксисом?источник
{ }
кнопку в редакторе. Наслаждайтесь!