Может ли кто-нибудь объяснить мне, что такое running total и SQL self-join в этом руководстве?

StackOverflow https://stackoverflow.com/questions/2529367

  •  22-09-2019
  •  | 
  •  

Вопрос

Я перечитывал этот учебник здесь: http://www.1keydata.com/sql/sql-running-totals.html и все это имело смысл, пока внезапно не стало до смешного невероятно сложным, когда дело дошло до ранга, медианы, промежуточных итогов и т.д.Кто-нибудь может объяснить простым английским языком, как этот запрос приводит к текущему итогу?Спасибо!

Это было полезно?

Решение

Прежде чем я начну, я не видел этого раньше, и это не выглядит как ужасно понятный способ выполнить текущий итог.

Хорошо, вот запрос из руководства:

SELECT a1.Name, a1.Sales, SUM(a2.Sales) Running_Total
FROM Total_Sales a1, Total_Sales a2
WHERE a1.Sales <= a2.sales or (a1.Sales=a2.Sales and a1.Name = a2.Name)
GROUP BY a1.Name, a1.Sales
ORDER BY a1.Sales DESC, a1.Name DESC;

И пример выходных данных

Name    Sales   Running_Total
Greg     50     50
Sophia    40    90
Stella    20    110
Jeff      20    130
Jennifer  15    145
John      10    155

Простая часть этого запроса заключается в отображении данных о продажах для каждого сотрудника.Все, что мы делаем, это выбираем name и sales от каждого сотрудника и упорядочивая их по сумме продажи (по убыванию).Это дает нам наш базовый список.

Теперь для текущего итога нам нужна каждая строка, которая уже была отображена.Итак, мы объединяем таблицу против самой себя в каждой строке, которая уже была бы отображена:

WHERE a1.Sales <= a2.sales or (a1.Sales=a2.Sales and a1.Name = a2.Name)

Затем мы используем SUM агрегатная функция и группировка соответственно.Хороший способ понять это, если вы посмотрите на то, что произошло бы, если бы вы не использовали функцию group .Строка "София" выглядела бы примерно так:

Name    A1.Sales    A2.Sales
Sophia  40          50
Sophia    40         40

Заметили, как мы получили торговый ряд Грега?Группа подведет итоги, и вуаля!

Надеюсь, это поможет.Джо

Другие советы

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

Затем он группирует поля в левой части объединения и суммирует строки, к которым мы присоединяемся, таким образом, получается итоговый результат.Чтобы увидеть, как это работает, вы можете захотеть запустить его без суммирования и группировки, чтобы увидеть возвращаемые необработанные результаты.

Приведенный выше SQL дает другой результат в Sybase (ASE 15).Я думаю, причина в том, что 'order by' не применяется до времени отображения.Вот SQL и результат:

drop table Total_Sales
go
create table Total_Sales
(
    Name char(15),
    Sales  int
)

INSERT INTO Total_Sales VALUES( 'John', 10 )
INSERT INTO Total_Sales VALUES( 'Jennifer', 15)
INSERT INTO Total_Sales VALUES('Stella', 20 )
INSERT INTO Total_Sales VALUES('Sophia', 40 )
INSERT INTO Total_Sales VALUES('Greg', 50 )
INSERT INTO Total_Sales VALUES('Jeff', 20 )

SELECT a1.Name, a1.Sales, SUM(a2.Sales) Running_Total 
FROM Total_Sales a1, Total_Sales a2 
WHERE a1.Sales <= a2.Sales or (a1.Sales=a2.Sales and a1.Name = a2.Name) 
GROUP BY a1.Name, a1.Sales 
ORDER BY a1.Sales DESC, a1.Name DESC

Результат:

Name           Sales Running_Total   
Greg            50  50   
Sophia          40  90   
Stella          20  130 --note that two running totals are the same! 
Jeff            20  130  
Jennifer        15  145  
John            10  155  

Боб

Я также получаю тот же неверный вывод, что и Bob выше, где текущий итог разбивается на Stella & Jeff, у которых одинаковый номер продаж.Я использую SQL Server 2014 Management Studio Express.Я не думаю, что решение веб-сайта на самом деле правильное.Я выполнил объединение на основе названия, а не на основе продаж, и получил их, которые дают правильный текущий итог:

select a1.name
, a1.sales
, sum(a2.sales) 'running_total'
from #total_sales a1
inner join #total_sales a2 on a1.name <= a2.name 
group by a1.name, a1.sales
order by sum(a2.sales);

Урожайность:

name      sales  running_total
Stella    20     20
Sophia    40     60
John      10     70
Jennifer  15     85
Jeff      20     105
Greg      50     155

Вы также можете выполнить приведенный ниже вариант, если вам неудобна сортировка по совокупности.Это изменяет порядок, но итоговый результат по-прежнему остается правильным:

select a1.name
, a1.sales
, sum(a2.sales) 'running_total'
from #total_sales a1
inner join #total_sales a2 on a1.name >= a2.name 
group by a1.name, a1.sales
order by a1.name;

Урожайность:

name     sales  running_total
Greg     50     50
Jeff     20     70
Jennifer 15     85
John     10     95
Sophia   40     135
Stella   20     155
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top