TSQL проверяет, существует ли определенная последовательность строк - PullRequest
1 голос
/ 16 марта 2012

У меня есть таблица, содержащая поля:

History_ID   ORDER_ID   Previous_STATUS_ID   Next_STATUS_ID
0            2          null                 1
1            2          1                    2
2            2          2                    3
3            1          null                 1
4            2          3                    4
5            3          null                 2
6            2          4                    1
7            2          1                    2
8            2          2                    5
9            7          3                    4

10 4 6 2 11 9 3 5

Содержит мой заказ ID и ID статуса. В основном таблица содержит историю STATUS для каждого заказа.

Я хотел бы проверить, имеет ли конкретный заказ определенную последовательность заказов.

Пример: если идентификатор заказа 4 имел состояния 2,4,3,1, вернуть true

Статусы должны быть один за другим, поэтому после 2 должно быть 4, после 4 - 3 и после 1. 1. 1016 *

Эти последовательности дают мне информацию (которая будет отображаться в моем отчете) о потоке определенного заказа.

Мне нужно проверить последовательности такого типа:

  • 1,2,3
  • 1,4,3,2
  • 4,2
  • (1 или 2 или 3 или 4), 5,3 - один из тех 4, затем 5 и затем 3

У меня нет идеи, как начать с такого запроса: /

EDIT:
Мой окончательный отчет представляет собой таблицу, содержащую информацию о заказах, например, так:

Orders type  Count      ...
Profile1     145        ...
Profile2     217        ...
Profile3     12         ...
Profile4     2          ...

У меня около 800 000+ заказов, и мой отчет должен составляться каждый день, поэтому вместо того, чтобы делать отчет для всей таблицы (проверяя эти STATES и агрегируя информацию из других таблиц), я решил создать таблицу отчетов:

Order_ID   Profile   Order_date   Customer_profile     ...
1          5        '2008-01-03'  2
4          1        '2009-04-10'  3
3          7        '2011-11-03'  1
4523       2        '2012-11-03'  5

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

Например, посмотрите на заказ с ID = 2
Next_STATUS_ID ale примерно так: 1,2,3,4,1,2,5 ... Я хочу проверить, есть ли в этом порядке изменение истории, например, 1,2,5, поэтому моя функция (оператор select) должна повторить 1, если она находит эти идентификаторы в указанном порядке.

Ответы [ 2 ]

1 голос
/ 16 марта 2012

Я думаю, что это можно решить с помощью рекурсивного CTE:

with change_tree as 
(
  SELECT order_id,
         previous_status_id, 
         next_status_id,
         cast(next_status_id as varchar(max)) as status_path
  FROM status_change
  WHERE previous_status_id = 1
    AND order_id = 2

  UNION ALL 

  SELECT sc.order_id,
         sc.previous_status_id,
         sc.next_status_id,
         ct.status_path + ',' + cast(sc.next_status_id as varchar(max))
  FROM status_change sc 
    JOIN change_tree ct ON ct.next_status_id = sc.previous_status_id AND ct.order_id = sc.order_id
)
SELECT *
FROM change_tree
WHERE status_path = '2,3,5';

По сути, это (рекурсивно) объединить все значения next_status_id в одну строку, с которой вы можете сравнить.

Из ваших примеров данных мне не ясно, какая строка отмечает «начало» истории изменения статуса заказа. Вам нужно будет изменить положение в первой части объединения, чтобы выбрать правильную «стартовую» строку.

0 голосов
/ 16 марта 2012

Я мог бы подойти к этому так:

  1. Создать хранимую процедуру для проверки последовательности

    а. Выберите строки по идентификатору заказа в локальной таблице @variable в порядке идентификатора истории, начиная с столбца IDENTITY с начальным значением 1 и шагом 1

    .

    б. Что вы будете делать дальше, зависит от того, насколько сложным / причудливым / ремонтопригодным вы хотите, чтобы это было. Быстрое и грязное решение состояло бы в том, чтобы составить список идентификаторов, разделенных запятыми, из переменной таблицы, по порядку, и сравнить их с некоторыми жестко закодированными последовательностями.

    Существует несколько способов построения строк с разделителями-запятыми из нескольких строк.

    с. Для более изящного решения вы можете создать новую таблицу (что-то вроде «HistoryTestSequence»), которая будет выглядеть примерно так (для иллюстрации теста 1,4,3,2):

    TestNumber | SequenceOrder | CompareValue
    -----------+---------------+-------------
             1 |             1 |            1
             1 |             2 |            4
             1 |             3 |            3
             1 |             4 |            2
    

    Затем можно попытаться JOIN к этому из переменной таблицы, сопоставив столбец идентификаторов со столбцом SequenceOrder и идентификатор истории с столбцом CompareValue, WHERE TestNumber = 1. Если COUNT() строк, возвращенных после JOIN, равняется COUNT(*) FROM HistoryTestSequence WHERE TestNumber = 1, то вы сопоставили свою последовательность. Вам просто нужно повторить тест для каждого набора возможных последовательностей, что вы можете сделать в цикле или вручную.

Если бы у меня было больше времени, я хотел бы собрать пример, но сейчас я позволю вам попробовать. Последний пример, вероятно, излишним.

Наконец, просто имейте в виду, что тестирование с использованием столбцов идентификаторов опасно - идентификаторы, созданные последовательностями на одном сервере, могут иметь разные на другом сервере (например, если у вас есть производственные экземпляры и экземпляры SQL-сервера UAT, которые немного не соответствуют синхронизации).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...