Сложная задача ранжирования TSQL

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

К сожалению, я не могу придумать правильный запрос, чтобы получить желаемый результат.

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

У меня есть следующая таблица CTE содержит набор значений данных:

 type    model    price    code
 Shoes    1298    700,00    1
 Shoes    1298    950,00    6
 Shoes    1298    1050,00    4
 Shoes    1321    970,00    2
 Shoes    1750    1200,00    3
 Shoes    1752    1150,00    5
 Pants    1121    850,00    2
 Pants    1121    850,00    4
 Pants    1121    850,00    5
 Pants    1232    350,00    8
 Pants    1232    350,00    9
 Pants    1232    400,00    7
 Pants    1232    600,00    1
 Pants    1233    600,00    3
 Pants    1233    950,00    6
 Pants    1233    970,00    12
 Pants    1233    980,00    11
 Pants    1260    350,00    10
 Hats    1276    400,00    1
 Hats    1288    400,00    6
 Hats    1401    150,00    4
 Hats    1408    270,00    5
 Hats    1433    270,00    2
 Hats    1434    290,00    3

Единая нумерация записей CTE должна выполняться следующим образом: сначала идут первые модели таблиц (Shoes, Pants and Hats), затем последние модели, затем - вторые модели в таблицах, предпоследние и т. Д. В случае исчерпания моделей определенного типа, нумеруйте только оставшиеся модели других типов.

Вот желаемый результат:

Id    type    model    price           code
 1    Shoes    1298    700.0000       1
 2    Pants    1232    600.0000       1
 3    Hats    1276    400.0000        1

 4    Shoes    1298    950.0000       6
 5    Pants    1233    970.0000       12
 6    Hats    1288    400.0000        6

 7    Shoes    1321    970.0000       2
 8    Pants    1121    850.0000       2
 9    Hats    1433    270.0000        2

 10    Shoes    1752    1150.0000     5
 11    Pants    1233    980.0000      11
 12    Hats    1408    270.0000       5

 13    Shoes    1750    1200.0000     3
 14    Pants    1233    600.0000      3
 15    Hats    1434    290.0000       3

 16    Shoes    1298    1050.0000     4 
 17    Pants    1260    350.0000      10
 18    Hats    1401    150.0000       4

 19    Pants    1121    850.0000      4
 20    Pants    1232    350.0000      9

 21    Pants    1121    850.0000      5
 22    Pants    1232    350.0000      8

 23    Pants    1233    950.0000      6
 24    Pants    1232    400.0000      7

Я обновил желаемый результат (добавлен код столбца), чтобы лучше понять идею сортировки. Это должно быть выполнено с перемежением с первыми закодированными номерами (т. Е. С наименьшим кодом) типов идет первым, затем последние кодированные номера (т. Е. С наивысшим кодом) типов идут вторым, затем сначала кодируется, кто слева, идет первым, а затем последний кодируется, кто слева и так далее.

3 ответа

Вы хотите, чтобы значение чередовалось. Вот как вы можете сделать это:

with cte as ( . . . )
select row_number() over (order by seqnum, charindex(type, 'ShoesPantsHats')) as id,
       t.*
from (select cte.*,
             row_number() over (partition by type order by (select NULL)) as seqnum
      from cte
     ) t
order by seqnum,
         charindex(type, 'ShoesPantsHats');

Обратите внимание order by пункт для row_number(), Таблицы SQL по своей природе неупорядочены, и если вы заботитесь о порядке следования результатов внутри каждого типа, поместите туда соответствующую логику.

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

WITH    cte1 AS ( SELECT   * ,
                        ROW_NUMBER() OVER (PARTITION BY type ORDER BY model, code) rn1
                  FROM     @t),
        cte2 AS ( SELECT   * ,
                        ROW_NUMBER() OVER (PARTITION BY rn1 ORDER BY 
                                            CASE type WHEN 'Shoes' THEN 1 
                                                      WHEN 'Pants' THEN 2 
                                                      WHEN 'Hats' THEN 3 END) rn2
                  FROM     cte1 )
SELECT  * ,
        ROW_NUMBER() OVER (ORDER BY rn1, rn2) rn
FROM    cte2

Выход:

type    model   price   code    rn1 rn2 rn
Shoes   1298    700.00  1       1   1   1
Pants   1121    850.00  2       1   2   2
Hats    1276    400.00  1       1   3   3
Shoes   1298    1050.00 4       2   1   4
Pants   1121    850.00  4       2   2   5
Hats    1288    400.00  6       2   3   6
Shoes   1298    950.00  6       3   1   7
Pants   1121    850.00  5       3   2   8
Hats    1401    150.00  4       3   3   9
Shoes   1321    970.00  2       4   1   10
Pants   1232    600.00  1       4   2   11
Hats    1408    270.00  5       4   3   12
Shoes   1750    1200.00 3       5   1   13
Pants   1232    400.00  7       5   2   14
Hats    1433    270.00  2       5   3   15
Shoes   1752    1150.00 5       6   1   16
Pants   1232    350.00  8       6   2   17
Hats    1434    290.00  3       6   3   18
Pants   1232    350.00  9       7   1   19
Pants   1233    600.00  3       8   1   20
Pants   1233    950.00  6       9   1   21
Pants   1233    980.00  11      10  1   22
Pants   1233    970.00  12      11  1   23
Pants   1260    350.00  10      12  1   24

Rn содержит желаемые значения.

Попробуй это,

with cte as (select type, model,price, ROW_NUMBER() over (partition by type order by type) as rowid from temp)
select * from cte order by rowid, type
Другие вопросы по тегам