Вопрос

Наличие таблицы со следующими полями:

Порядок, Группа, Последовательность

требуется, чтобы все заказы в данной группе образовывали непрерывную последовательность.Например:1,2,3,4 или 4,5,6,7.Как я могу проверить с помощью одного SQL-запроса, какие заказы не соответствуют этому правилу?Спасибо.

Example data:

Order   Group   Sequence
1   1   3
2   1   4
3   1   5
4   1   6
5   2   3
6   2   4
7   2   6

Expected result:
Order
5
6
7

Также принимается, если запрос возвращает только группу, которая имеет неправильную последовательность, 2 для примера данных.

Это было полезно?

Решение

Предполагая, что последовательности генерируются и, следовательно, не могут быть продублированы:


SELECT group
 FROM theTable
 GROUP BY group
 HAVING MAX(Sequence) - MIN(Sequence) <> (COUNT(*) - 1);

Другие советы

Как насчет этого?

выберите Группу из Таблицы
группа за группой
имеющий количество (Последовательность) <= макс (Последовательность)-мин(Последовательность)

[Редактировать] Это предполагает, что Последовательность не допускает дубликатов внутри определенной группы.Возможно, было бы лучше использовать:
количество != макс - мин + 1

[Правка еще раз] О, все еще не идеально.Однако другой запрос для удаления дубликатов позаботился бы об этом.

[Редактировать последнее] Исходный запрос отлично работал в sqlite, который у меня был доступен для быстрого тестирования.Это гораздо более щадящий метод, чем SQL server.Спасибо Беллу за подсказку.

Лично я думаю, что я бы подумал о переосмыслении этого требования.Природа реляционных баз данных такова, что пробелы в последовательностях могут легко возникать из-за отката записей.Например, предположим, что заказ начинает создавать в нем четыре элемента, но по какой-то причине один из них завершается неудачей и выполняется откат.Если бы вы предварительно вычислили последовательности вручную, то у вас был бы пробел в том, что откат не является последним.В других сценариях может возникнуть пробел из-за того, что несколько пользователей ищут значения последовательности примерно в одно и то же время или если в последнюю минуту клиент удалил одну запись из заказа.Что вы, честно говоря, хотите получить от наличия непрерывных последовательностей, чего вы не получаете от отношений родитель-потомок?

Этот SQL выбирает порядки 3 и 4, которые не имеют непрерывных последовательностей.

DECLARE @Orders TABLE ([Order] INTEGER, [Group] INTEGER, Sequence INTEGER)

INSERT INTO @Orders VALUES (1, 1, 0)
INSERT INTO @Orders VALUES (1, 2, 0)
INSERT INTO @Orders VALUES (1, 3, 0)

INSERT INTO @Orders VALUES (2, 4, 0)
INSERT INTO @Orders VALUES (2, 5, 0)
INSERT INTO @Orders VALUES (2, 6, 0)

INSERT INTO @Orders VALUES (3, 4, 0)
INSERT INTO @Orders VALUES (3, 6, 0)

INSERT INTO @Orders VALUES (4, 1, 0)
INSERT INTO @Orders VALUES (4, 2, 0)
INSERT INTO @Orders VALUES (4, 8, 0)

SELECT o1.[Order]
FROM @Orders o1
     LEFT OUTER JOIN @Orders o2 ON o2.[Order] = o1.[Order] AND o2.[Group] = o1.[Group] + 1
WHERE o2.[Order] IS NULL
GROUP BY o1.[Order]
HAVING COUNT(*) > 1

Итак, ваша таблица имеет вид

Order Group Sequence
1     1     4
1     1     5
1     1     7

.. и вы хотите выяснить, что 1,1,6 отсутствует?

С

select
  min(Sequence) MinSequence, 
  max(Seqence) MaxSequence 
from 
  Orders 
group by 
  [Order], 
  [Group]

вы можете узнать границы для данного Порядка и Группы.

Теперь вы можете смоделировать правильные данные с помощью специального таблица чисел, который просто содержит все отдельные числа, которые вы когда-либо могли бы использовать для последовательности. Здесь это хороший пример такой таблицы чисел.Не важно, как вы его создаете, вы также можете создать файл Excel со всеми числами от x до y и импортировать этот лист Excel.

В моем примере я предполагаю такую таблицу чисел под названием "Числа" только с одним столбцом "n".:

select 
  [Order], 
  [Group], 
  n Sequence
from
  (select min(Sequence) MinSequence, max(Seqence) MaxSequence from [Table] group by [Order], [Group]) MinMaxSequence
  left join Numbers on n >= MinSequence and n <= MaxSequence

Поместите этот SQL в новое представление.В моем примере я буду называть представление "vwCorrectOrders".

Это дает вам данные, в которых последовательности являются непрерывными.Теперь вы можете объединить эти данные с исходными данными, чтобы выяснить, какие последовательности отсутствуют:

select 
  correctOrders.*
from
  vwCorrectOrders co 
  left join Orders o on 
      co.[Order] = o.[Order] 
  and co.[Group] = o.[Group]
  and co.Sequence = o.Sequence
where
  o.Sequence is null

Должен дать вам

Order Group Sequence
1     1     6

Через некоторое время я пришел к следующему решению.Кажется, это работает, но крайне неэффективно.Пожалуйста, добавляйте любые предложения по улучшению.

SELECT OrdMain.Order
  FROM ((Orders AS OrdMain
  LEFT OUTER JOIN Orders AS OrdPrev ON (OrdPrev.Group = OrdMain.Group) AND (OrdPrev.Sequence = OrdMain.Sequence - 1))
  LEFT OUTER JOIN Orders AS OrdNext ON (OrdNext.Group = OrdMain.Group) AND (OrdNext.Sequence = OrdMain.Sequence + 1))
WHERE ((OrdMain.Sequence < (SELECT MAX(Sequence) FROM Orders OrdMax WHERE (OrdMax.Group = OrdMain.Group))) AND (OrdNext.Order IS NULL)) OR
      ((OrdMain.Sequence > (SELECT MIN(Sequence) FROM Orders OrdMin WHERE (OrdMin.Group = OrdMain.Group))) AND (OrdPrev.Order IS NULL))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top