Почему этот оператор SQL SUM правильный? - PullRequest
2 голосов
/ 03 августа 2010

В моей схеме у меня есть таблица Projects и таблица Tasks.Каждый проект состоит из задач.У каждой задачи есть Hours и PercentComplete.

Пример таблицы:

ProjectID    TaskID    Hours   PercentComplete
1            1         100     50
1            2         120     80

Я пытаюсь получить взвешенный процент выполнения для проекта.Я делаю это, используя следующую инструкцию SQL:

SELECT P.ProjectID, P.ProjectName, SUM(T.Hours) AS Hours, 
SUM(T.PercentComplete * T.Hours) / 100 AS CompleteHours, 
SUM(T.PercentComplete * T.Hours) / SUM(T.Hours) AS PercentComplete
FROM Projects AS P INNER JOIN
        Tasks AS T ON T.ProjectID = P.ProjectID
WHERE     (P.ProjectID = 1)

Мой вопрос касается этой части этой инструкции:

SUM(T.PercentComplete * T.Hours) / SUM(T.Hours) AS PercentComplete

Это дает мне правильный взвешенный процент для этого проекта (вслучай данных образца выше, 66%).Но я не могу понять, почему это происходит.

Почему этот запрос работает?

Ответы [ 5 ]

4 голосов
/ 03 августа 2010
  • SUM(T.PercentComplete * T.Hours) / 100 - количество полных часов.
  • SUM(T.Hours) - общее количество часов.
  • Соотношение этих двух величин, т.е.

    (SUM(T.PercentComplete * T.Hours) / 100) / SUM(T.Hours)
    

    - это доля завершенных часов (она должна быть между 0 и 1).

  • Умножение на 100 дает процент.

Я предпочитаю хранить проценты, подобные этому, в базе данных и перемещать их на уровень представления.Было бы намного проще, если бы в базе данных хранились «количество выполненных часов» и «общее количество часов» и не сохранялись проценты вообще.Дополнительные коэффициенты 100 в расчетах запутывают проблему.

2 голосов
/ 03 августа 2010

Как правило, вы находите количество завершенных часов по общему количеству часов.

SUM(T.PercentComplete * T.Hours) вычисляет общее количество часов, которое вы отработали. (100 * 50) = 50 * 100 + (120 * 80) = 146 * 100 - числитель. 146 часов было завершено для этой работы, и мы сохраняем множитель 100 для процента (потому что это [0-100] вместо [0-1])

Затем мы находим общее количество отработанных часов, SUM(T.Hours), что составляет 100 + 120 = 220.

Затем, разделив, мы находим средневзвешенное значение. (146 * 100) / 220 = 0.663636364 * 100 = 66.4%

Это то, что вас интересует?

1 голос
/ 03 августа 2010

Он рассчитывает две суммы по отдельности, складывая значение для каждой строки, а затем делит их в конце

SUM (T.PercentComplete * T.Hours)

50*  100 +
80 * 120
-------
14,600

SUM (T.Hours)

100 +
120
---
220

Затем деление в конце

14,600 / 220
------------
66.3636

Редактировать Согласно комментарию HLGEM, оно фактически вернет 66 из-за целочисленного деления.

0 голосов
/ 03 августа 2010

SUM peratiorn сначала умножает столбцы, затем добавляет

( 100* 50+ 120* 80)  / (100+ 120)
0 голосов
/ 03 августа 2010

Агрегатные функции, такие как SUM (), работают с набором данных, определенным предложением GROUP BY. Так что, если вы сгруппируете по ProjectID, ProjectName, функции будут разбиты на части.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...