Oracle SQL Count или Sum в случае запроса? - PullRequest
0 голосов
/ 02 октября 2018

Я исследовал пять различных потоков в StackOverflow, и я чувствую, что подхожу близко, но сигары все еще нет.Моя исходная таблица имеет несколько разделов, и каждый раздел имеет несколько строк, и каждая строка имеет несколько позиций.Я хочу иметь возможность запросить результат, в котором перечислены раздел, строка, позиция, сколько позиций находится над позицией в строке (номер позиции ниже) и сколько позиций находится под позицией в строке (номер позиции больше).

Вот что у меня есть:

SELECT section, 
       row, 
       position AS P, 
       SUM(case when position < P then 1 else 0 end) AS Above, 
       SUM(case when position > P then 1 else 0 end) AS Below 
FROM OriginalTable 
GROUP BY section, row, position 
ORDER BY section, row, position

Случай суммы не распознает P как позицию, и когда я меняю P на число, суммы уходят.

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Я бы просто использовал row_number():

SELECT section, row, position AS P, 
       ROW_NUMBER() OVER (PARTITION BY section, row ORDER BY position ASC) - 1 as Above,
       ROW_NUMBER() OVER (PARTITION BY section, row ORDER BY position DESC) - 1 as Below
FROM OriginalTable
ORDER BY section, row, position;

Если у вас есть дубликаты, тогда проблема немного сложнее (хотя GROUP BY решит эту проблему).Вы можете хотеть DENSE_RANK() вместо ROW_NUMBER().

0 голосов
/ 02 октября 2018

Одним из возможных решений является коррелированный подзапрос, получающий count() более низких / более высоких позиций для раздела и строки.

SELECT ot1.section,
       ot1.row,
       ot1.position,
       (SELECT count(*)
               FROM originaltable ot2
               WHERE ot2.section = ot1.section
                     AND ot2.row = ot2.row
                     AND ot2.position > ot1.position) above,
       (SELECT count(*)
               FROM originaltable ot2
               WHERE ot2.section = ot1.section
                     AND ot2.row = ot2.row
                     AND ot2.position < ot1.position) below
      FROM originaltable ot1
      ORDER BY ot1.section,
               ot1.row,
               ot1.position;

Еще один использует оконную версию count().

SELECT ot1.section,
       ot1.row,
       ot1.position,
       count(*) OVER (PARTITION BY ot1.section,
                                   ot1.row
                      ORDER BY ot1.position
                      RANGE BETWEEN CURRENT ROW
                                    AND UNBOUNDED FOLLOWING) - 1 above
       count(*) OVER (PARTITION BY ot1.section,
                                   ot1.row
                      ORDER BY ot1.position
                      RANGE BETWEEN UNBOUNDED PRECEDING
                                    AND CURRENT ROW) - 1 below
      FROM originaltable ot1
      ORDER BY ot1.section,
               ot1.row,
               ot1.position;
...