2016-08-29 4 views
0

Предположим, у меня есть набор данных: ID NEXT ORDER 1456 1679 1 1679 1679 2 1578 1679 3 9492 1679 4 Данные для заказа на основе ротации

Единственный столбец этого набора данных, который когда-либо изменений ДАЛЕЕ. Идентификатор всегда уникален, NEXT всегда коррелирует с одним идентификатором и будет дублироваться в каждой строке. ORDER - последовательный int.

мне нужно OrderBy или другой SQL заявление, которое будет выполнять следующий вид:


СЛЕДУЮЩЕЮ ID всегда в нижней части заказа.

Идентификатор, который имеет последовательно больше заказ после заказа следующего всегда является в верхних

Упорядочение затем последовательные, начиная со вторым по ORDER верхней строки существ следующего после того, в верхней строке в


Пример:

для приведенных выше таблиц упорядочения будет 1578 9492 1456 1679


Другая таблица, где рядом изменился:

ID NEXT ORDER 1456 1578 1 1679 1578 2 1578 1578 3 9492 1578 4

будет:

9492 1456 1679 1578

+0

также, пожалуйста, помечать соответствующую базу данных, которую вы используете, как SQLServer, Oracle, MySQL, Postgres .. – TheGameiswar

+0

Что делать, если NEXT является наивысшим порядком, например 9492? Вернуть заказ, как он есть в таблице? – Matt

+0

@Matt это правильно! –

ответ

2
-- Exsting query 
select ... 
from ... 

-- New 
INNER JOIN (select top 1 [ORDER] FROM [MyTable] WHERE ID=[Next]) o ON 1=1 

-- Rest of existing query 
WHERE ... 

--ORDER BY clause 
ORDER BY CASE WHEN [order] > o.[Order] THEN -9999999+[order] else [order] end 

SQLFiddle
(Fiddle использует Postgresql, как это кажется Sql Server будет нарушена на данный момент).

+0

Быстрое и грязное решение, но оно работает. благодаря! –

0

Это должно работать:

SAMPLE DATA:

IF OBJECT_ID('tempdb..#temp') IS NOT NULL 
    DROP TABLE #temp; 

CREATE TABLE #temp(ID  INT 
       , [NEXT] INT 
       , [ORDER] INT); 

INSERT INTO #temp 
VALUES 
     (1456 
    , 1679 
    , 1), 
     (1679 
    , 1679 
    , 2), 
     (1578 
    , 1679 
    , 3), 
     (9492 
    , 1679 
    , 4); 

QUERY:

DECLARE @rowcount INT; 

SELECT @rowcount = COUNT(1) 
FROM #temp 
WHERE [ORDER] > 
       (SELECT [ORDER] 
       FROM #temp 
       WHERE ID = [NEXT]); 

SELECT ID 
FROM 
     (SELECT * 
       , rn = ROW_NUMBER() OVER(ORDER BY [ORDER]) 
      FROM #temp 
      WHERE [ORDER] > 
         (SELECT [ORDER] 
         FROM #temp 
         WHERE ID = [NEXT]) 
         UNION 
         SELECT * 
          , rn = @rowcount + ROW_NUMBER() OVER(ORDER BY [ORDER]) 
         FROM #temp 
         WHERE [ORDER] <= 
             (SELECT [ORDER] 
             FROM #temp 
             WHERE ID = [NEXT])) AS A 
ORDER BY rn; 

РЕЗУЛЬТАТ:

enter image description here

1

Подобный ответ Иоиля ОНЛ у используя оконную функцию вместо INNER JOIN или CROSS ОТНОСИТЬСЯ:

SELECT 
    * 
FROM 
    #temp t 
ORDER BY 
    CASE 
     WHEN t.[Order] > MAX(CASE WHEN ID = [NEXT] THEN [ORDER] END) OVER() THEN -999999999 + t.[Order] 
     ELSE t.[Order] 
    END 

А вот версия с использованием CROSS ОТНОСИТЬСЯ

SELECT 
    t.* 
FROM 
    #temp t 
    CROSS APPLY (SELECT [Order] FROM #temp WHERE ID = NEXT) n 
ORDER BY 
    CASE 
     WHEN t.[Order] > n.[Order] THEN -99999999 + t.[Order] 
     ELSE t.[Order] 
    END 
+0

I _ ** love ** _ APPLY, но поскольку результат внутреннего запроса должен быть последовательным для каждой строки, я думаю, что INNER JOIN - лучший вариант в этом случае.Тем не менее, один для функции оконной обработки. Вероятно, это лучший вариант. Скорее всего, быстрее, и вы содержите код для упорядочивания результатов целиком в предложении ORDER BY. –

+0

@JoelCoehoorn Я не уверен, что я следую за тем, почему вы чувствуете, что крест применяется не приведет к тому же результату, что и ваш в каждом случае? CROSS APPLY в этом случае в основном совпадает с вашим внутренним соединением, потому что вы присоединяетесь к 1 = 1, и я не передаю какое-либо значение из таблицы в APPLY, и поэтому оно полностью содержится в заказе так же, как ваше. Верхняя часть - с функцией окна с условной агрегацией, поэтому нет необходимости применять ее или соединить с ней. – Matt

+0

Да, он вернет тот же результат. У меня меньше уверенности в способности оптимизатора запроса распознать оператор внутри оператора приложения, не использует какие-либо данные из внешнего запроса, хотя я признаюсь, что на самом деле я не смотрел план выполнения. –

Смежные вопросы