Лучший способ агрегировать данные - обновить запрос или подзапрос? - PullRequest
0 голосов
/ 31 декабря 2011

Я пытаюсь объединить некоторые данные заказов клиентов в одну таблицу для анализа.Данные - это количество продуктов, которые заказывает клиент, затем пытается определить, является ли заказ небольшим, средним или крупным заказом, а затем определить общее количество продуктов, которые он купил, и стоимость заказа на OrderSize.

Малый заказ - 1 - 2 товара
Средний заказ - 3 - 4 товара
Большой заказ -> = 5 товаров

Вот данные:

CustomerID  OrderID   OrderSize OrderTotal
1           800       1         $20
2           801       1         $10
3           802       4         $85
1           803       1         $30
2           804       8         $120
3           805       1         $40

Вот таблица, которую я пытаюсь построить (проще просто опубликовать изображение): Table Screenshot

Я мог бы выполнить такой запрос на обновление, чтобы заполнить таблицу:

-- Создать таблицу -

CREATE TABLE Customers (
    CustomerID varchar(10) PRIMARY KEY,
    SmallOrderCount int,
    SmallOrderProducts int,
    SmallOrderTotal money,
    MedOrderCount int,
    MedOrderProducts int,
    MedOrderTotal money,
    LargeOrderCount int,
    LargeOrderProducts int,
    LargeOrderTotal money
);

- Вставить уникальных клиентов -

INSERT INTO Customers
SELECT CustomerID FROM Orders GROUP BY CustomerID;

- Обновить для заполнения информации о заказе -

UPDATE Customers
SET SmallOrderCount = (SELECT count(*) FROM Orders WHERE OrderSize BETWEEN 1 AND 2 AND Orders.CustomerID = Customers.CustomerID);

UPDATE Customers 
SET SmallOrderProducts = (SELECT sum(OrderSize) FROM Orders WHERE OrderSize BETWEEN 1 AND 2 AND Orders.CustomerID = Customers.CustomerID);

UPDATE Customers 
SET SmallOrderTotal = (SELECT sum(OrderTotal) FROM Orders WHERE OrderSize BETWEEN 1 AND 2 AND Orders.CustomerID = Customers.CustomerID);

Тогда я мог бы повторить это для оставшихся 6 столбцов.

Однако, это похоже на большую работу.Есть ли способ заполнить мою таблицу Customer с помощью подзапроса, который может быть менее трудоемким?Или мой подход выше самого прямого?

Ответы [ 4 ]

1 голос
/ 31 декабря 2011

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

WITH cteOrders AS (
    SELECT CustomerID,
        CASE WHEN OrderSize BETWEEN 1 AND 2 THEN OrderSize END SmallOrderProducts,
        CASE WHEN OrderSize BETWEEN 1 AND 2 THEN OrderTotal END SmallOrderTotal,
        CASE WHEN OrderSize BETWEEN 3 AND 4 THEN OrderSize END MediumOrderProducts,
        CASE WHEN OrderSize BETWEEN 3 AND 4 THEN OrderTotal END MediumOrderTotal,
        CASE WHEN OrderSize > 4 THEN OrderSize END LargeOrderProducts,
        CASE WHEN OrderSize > 4 THEN OrderTotal END LargeOrderTotal
    FROM Orders
)
SELECT CustomerID,
        COUNT(SmallOrderProducts) SmallOrderCount,
        COALESCE(SUM(SmallOrderProducts), 0) SmallOrderProducts,
        COALESCE(SUM(SmallOrderTotal), 0) SmallOrderTotal,
        COUNT(MediumOrderProducts) MediumOrderCount,
        COALESCE(SUM(MediumOrderProducts), 0) MediumOrderProducts,
        COALESCE(SUM(MediumOrderTotal), 0) MediumOrderTotal,
        COUNT(LargeOrderProducts) LargeOrderCount,
        COALESCE(SUM(LargeOrderProducts), 0) LargeOrderProducts,
        COALESCE(SUM(LargeOrderTotal), 0) LargeOrderTotal
    FROM cteOrders
    GROUP BY CustomerID
1 голос
/ 31 декабря 2011

Одного insert должно быть достаточно:

INSERT INTO Customers(CustomerID,SmallOrderCount,SmallOrderProducts,
   SmallOrderTotal)     
SELECT a.CustomerID, COUNT(a.*) as cnt, sum(a.OrderSize) as OrderSize,
    sum(a.OrderTotal) as OrderTotal 
   FROM Orders a
   WHERE a.OrderSize BETWEEN 1 AND 2 
   GROUP BY a.CustomerID

В приведенном выше запросе будут вставлены только клиенты, размер заказа которых находится в диапазоне от 1 до 2. Если вам нужно добавить и других, вы можете использовать:

INSERT INTO Customers(CustomerID,SmallOrderCount,SmallOrderProducts,
   SmallOrderTotal)     
SELECT a.CustomerID, 
COUNT(CASE WHEN  a.OrderSize BETWEEN 1 AND 2  THEN 1 END) as cnt, 
sum(CASE WHEN  a.OrderSize BETWEEN 1 AND 2  THEN a.OrderSize ELSE 0 END) as OrderSize,
sum(CASE WHEN  a.OrderSize BETWEEN 1 AND 2  THEN a.OrderTotal ELSE 0 END ) as OrderTotal 
FROM Orders a
GROUP BY a.CustomerID
1 голос
/ 31 декабря 2011

Вы можете сделать все в одной команде INSERT с помощью операторов CASE:

INSERT INTO Customers
SELECT CustomerID
      ,sum(CASE WHEN OrderSize BETWEEN 1 AND 2 THEN 1 ELSE 0 END) AS SmallOrderCount
      ,sum(CASE WHEN OrderSize BETWEEN 1 AND 2 THEN OrderSize ELSE 0 END) AS SmallOrderProducts
      ,sum(CASE WHEN OrderSize BETWEEN 1 AND 2 THEN OrderTotal ELSE 0 END) AS SmallOrderTotal
      ,sum(CASE WHEN OrderSize BETWEEN 3 AND 4 THEN 1 ELSE 0 END) AS MedOrderCount
      ,sum(CASE WHEN OrderSize BETWEEN 3 AND 4 THEN OrderSize ELSE 0 END) AS MedOrderProducts
      ,sum(CASE WHEN OrderSize BETWEEN 3 AND 4 THEN OrderTotal ELSE 0 END) AS MedOrderTotal
      ,sum(CASE WHEN OrderSize > 4 THEN 1 ELSE 0 END) AS LargeOrderCount
      ,sum(CASE WHEN OrderSize > 4 THEN OrderSize ELSE 0 END) AS LargeOrderProducts
      ,sum(CASE WHEN OrderSize > 4 THEN OrderTotal ELSE 0 END) AS LargeOrderTotal
FROM   Orders
GROUP  BY CustomerID;

См. Эту рабочую демонстрацию для полного запроса данных .SE .

0 голосов
/ 31 декабря 2011

Это можно сделать с помощью одного оператора INSERT INTO SELECT

INSERT INTO Customers
SELECT * ,
 (SELECT count(*) FROM Orders WHERE OrderSize BETWEEN 1 AND 2 AND Orders.CustomerID = CustomerID),
 (SELECT sum(OrderSize) FROM Orders WHERE OrderSize BETWEEN 1 AND 2 AND Orders.CustomerID  = CustomerID)

 FROM CUSTOMERS
...