Проверка последовательности с помощью SQL-запроса - PullRequest
2 голосов
/ 29 апреля 2009

У меня есть таблица заказов, в которой хранятся все заказы из всех наших магазинов. Я написал запрос, чтобы проверить последовательность заказов для каждого магазина. Похоже, что так.

select WebStoreID, min(webordernumber), max(webordernumber), count(webordernumber) 
from orders
where ordertype = 'WEB' 
group by WebStoreID

Я могу проверить, все ли заказы присутствуют в этом запросе. номер веб-заказа - это число от 1 ... n.

Как мне написать запрос, чтобы найти пропущенные заказы без объединения во временную / другую таблицу?

Ответы [ 4 ]

6 голосов
/ 29 апреля 2009

Вы можете присоединиться к самой таблице, чтобы обнаружить строки, у которых нет предыдущей строки:

select cur.*
from orders cur
left join orders prev 
    on cur.webordernumber = prev.webordernumber + 1
    and cur.webstoreid = prev.webstoreid
where cur.webordernumber <> 1
and prev.webordernumer is null

Это позволит обнаружить пробелы в последовательности 1 ... n, но не обнаружит дубликаты.

4 голосов
/ 29 апреля 2009

Я бы сделал вспомогательную таблицу из «всех целых чисел от 1 до n» (см. http://www.sql -server-helper.com / functions / integer-table.aspx , чтобы узнать, как сделать это с функция SQL Server, но поскольку это то, что вам понадобится снова и снова, я все равно превращу ее в настоящую таблицу, и с любым механизмом SQL это легко сделать, всего один раз), а затем используйте вложенный запрос, SELECT value FROM integers WHERE value NOT IN (SELECT webordernumber FROM orders) & c , Также см. http://www.sqlmag.com/Article/ArticleID/99797/sql_server_99797.html о проблеме, аналогичной вашей, «обнаружение пробелов в последовательности чисел».

2 голосов
/ 19 февраля 2011

Если у вас есть функция rank (), но нет функции lag () (другими словами, SQL Server), вы можете использовать ее (рекомендуется http://www.sqlmonster.com/Uwe/Forum.aspx/sql-server-programming/10594/Return-gaps-in-a-sequence):

create table test_gaps_in_sequence (x int)
insert into test_gaps_in_sequence values ( 1 )
insert into test_gaps_in_sequence values ( 2 )
insert into test_gaps_in_sequence values ( 4 )
insert into test_gaps_in_sequence values ( 5 )
insert into test_gaps_in_sequence values ( 8 )
insert into test_gaps_in_sequence values ( 9 )
insert into test_gaps_in_sequence values ( 12)
insert into test_gaps_in_sequence values ( 13)
insert into test_gaps_in_sequence values ( 14)
insert into test_gaps_in_sequence values ( 29)

...

 select lower_bound
         , upper_bound
      from (select upper_bound
                 , rank () over (order by upper_bound) - 1 as upper_rank
              from (SELECT x+n as upper_bound
                      from test_gaps_in_sequence
                         , (SELECT 0 n
                            UNION
                            SELECT -1
                           ) T
                     GROUP BY x+n
                    HAVING MAX(n) = -1
                    ) upper_1
            ) upper_2
         , (select lower_bound
                 , rank () over (order by lower_bound) as lower_rank
              from (SELECT x+n as lower_bound
                      from test_gaps_in_sequence
                         , (SELECT 0 n
                            UNION
                            SELECT 1
                           ) T
                     GROUP BY x+n
                    HAVING MIN(n) = 1
                    ) lower_1
            ) lower_2
      where upper_2.upper_rank = lower_2.lower_rank
      order by lower_bound

... или, чтобы включить «внешние пределы»:

select lower_bound
     , upper_bound
  from (select upper_bound
             , rank () over (order by upper_bound) - 1 as upper_rank
          from (SELECT x+n as upper_bound
                  from test_gaps_in_sequence
                     , (SELECT 0 n
                        UNION
                        SELECT -1
                       ) T
                 GROUP BY x+n
                HAVING MAX(n) = -1
                ) upper_1
        ) upper_2
   full join (select lower_bound
             , rank () over (order by lower_bound) as lower_rank
          from (SELECT x+n as lower_bound
                  from test_gaps_in_sequence
                     , (SELECT 0 n
                        UNION
                        SELECT 1
                       ) T
                 GROUP BY x+n
                HAVING MIN(n) = 1
                ) lower_1
        ) lower_2
   on upper_2.upper_rank  = lower_2.lower_rank
     order by coalesce (lower_bound, upper_bound)
1 голос
/ 29 апреля 2009

Если ваша база данных поддерживает аналитические функции, то вы можете использовать запрос, например:

select prev+1, curr-1 from
( select webordernumber curr,
         coalesce (lag(webordernumber) over (order by webordernumber), 0) prev
  from   orders
)
where prev != curr-1;

Вывод покажет пробелы, например

prev+1 curr-1
------ ------
     3      7

будет означать, что числа от 3 до 7 включительно отсутствуют.

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