Агрегация одной таблицы SQL

Последние несколько дней я пытался найти способ извлечь очень важный набор информации из таблицы, которая содержит то, что я называю ежедневными подсчетами. У меня есть таблица, которая настроена следующим образом.

person|company|prod1|prod2|prod3|gen_date

В каждой компании работает несколько человек, и у каждого человека могут быть разные комбинации продуктов, которые они приобрели. То, что я пытался выяснить, — это оператор SQL, в котором будет указано количество людей, купивших определенный продукт в каждой компании. Итак, вывод, подобный этому:

Comp ABC | 13 Prod1 |  3 Prod2 | 5 Prod 3
Comp DEF |  2 Prod1 | 15 Prod2 | 0 Prod 3
Comp HIJ |  0 Prod1 |  0 Prod2 | 7 Prod 3 

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

Лучшее, что у меня есть сейчас, это 3 разных утверждения, которые могут выдавать эту информацию, если они выполняются сами по себе.

SELECT Count(person) as puchases, company 
FROM Sales  WHERE prod1 = '1' and gendate = '3/24/2010' 
Group BY company

person Lostdrifter    schedule 24.03.2010    source источник
comment
en.wikipedia.org/wiki/First_normal_form   -  person Ignacio Vazquez-Abrams    schedule 24.03.2010
comment
Это не нарушает 1NF. 3NF, возможно.   -  person Aaronaught    schedule 24.03.2010


Ответы (2)


SELECT      company,
            SUM(COALESCE(prod1, 0)) AS total_prod1,
            SUM(COALESCE(prod2, 0)) AS total_prod2,
            SUM(COALESCE(prod3, 0)) AS total_prod3
FROM        Sales  
WHERE       gendate = '2010-03-24' 
GROUP BY    company

Но вы определенно должны нормализовать свою таблицу - разделить ее на 4:

  • Компания,
  • Человек,
  • Товар,
  • Person_Product_Purchase (с датой покупки).
person van    schedule 24.03.2010
comment
Я согласен, что нормализовал бы данные, но для этого конкретного проекта это не вариант по причинам, которые я не буду упоминать. Но большое спасибо. Я не специалист по базам данных. - person Lostdrifter; 24.03.2010

Если вы просто хотите проверить, находится ли значение в каком-либо из полей продукта, то это просто делается с помощью оператора OR:

SELECT company, COUNT(person) as purchases
FROM Sales
WHERE (prod1 = '1' OR prod2 = '1' OR prod3 = '1')
AND gendate = '3/24/2010'
GROUP BY company

Однако это не будет работать очень хорошо, и вам будет трудно заставить его работать хорошо, потому что ваша схема не была нормализована должным образом. Если вы можете, вы должны исправить это примерно так:

Person (PersonID, CompanyID)
Sales (PurchaseID, PersonID, ProductID, GenDate)

Тогда этот запрос (и многие другие запросы) будет намного проще написать:

SELECT p.CompanyID, COUNT(*) AS purchases
FROM Person p
INNER JOIN Sales s
    ON s.PersonID = p.PersonID
WHERE s.ProductID = 1
AND s.GenDate = '20100324'
GROUP BY p.CompanyID
person Aaronaught    schedule 24.03.2010