Расширенный цикл в SQL - PullRequest
       4

Расширенный цикл в SQL

0 голосов
/ 18 октября 2018
create table Numbers(id int, Number float);
insert into Numbers(id, Number) 
    values  (1, 3.00), 
            (2, 3.30), 
            (3, 4.50), 
            (4, 2.25), 
            (5, 6.50);

select min(Number) from Numbers into @minNumber;
select id, Number, (Number - @minNumber) from Numbers;

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

3.00  3.00
3.30  0.30
4.50  1.50
2.25  -0.75
6.50  4.25

Сейчас он показывает только разницу между числом и минимумом всех чисел (2.25).Не уверен, как запустить цикл, чтобы он работал.

Ответы [ 3 ]

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

Вероятно, наиболее эффективный метод будет использовать переменные:

select n.*,
       (number -
        (case when (@min2 := @min) = NULL then 0  -- never happens
              when @min := least(coalesce(@min, n.number), n.number) = NULL then 0  -- never happens
              else coalesce(@min2, 0)
         end)
       ) as diff
from numbers n cross join
     (select @min := NULL) params
order by n.id;

DB Fiddle DEMO

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

Что не так с перекрестным соединением?

SELECT n.id, n.Number, n.Number - MIN(n2.Number)
FROM Numbers n
CROSS JOIN Numbers n2
WHERE 
    n2.id < n.id
GROUP BY  n.id, n.Number;

ДБ Fiddle Demo

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

Предполагая, что у вас есть столбец первичного ключа id. Всегда помните, что данные хранятся в неупорядоченном порядке, поэтому без PK мы действительно не можем определить «строки над» текущей строкой.

Вы можете использовать Коррелированные подзапросы , чтобы определить минимум Number из строк над текущей строкой (t2.id < t1.id)

Для первой строки не будет никакого числа «выше», поэтому нам придется использовать Coalesce() функция для рассмотрения null значения как 0:

DB Fiddle DEMO

SELECT 
  t1.id, 
  t1.Number, 
  (t1.Number - COALESCE((SELECT MIN(t2.Number)
                         FROM Numbers AS t2 
                         WHERE t2.id < t1.id),0)) AS difference 
FROM Numbers AS t1 
ORDER BY t1.id 

В MySQL 8.0.2 далее, мы можем использовать оконные функции с рамкой .Мы можем рассмотреть «увеличивающийся» кадр с самого начала (UNBOUNDED PRECEDING) до одной строки перед текущей строкой (1 PRECEDING) и определить минимальное значение.

Попробуйте выполнить следующее (для )Только для MySQL 8.0.2+ ):

Демонстрация DB Fiddle

SELECT 
  id, 
  Number, 
  (Number - 
   COALESCE(MIN(Number) OVER(ORDER BY id 
                             ROWS BETWEEN UNBOUNDED PRECEDING 
                              AND 1 PRECEDING)
            ,0)) AS difference 
FROM Numbers 
ORDER BY id 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...