'T-SQL: How to return separate columns of data for different date ranges selected from same table?
I am trying to get customer spending data by range from the orders table, but the script seems to always combine all the tables rows per customer id regardless of however I try to specify date ranges. Any guidance in how I can accomplish my goal here is very appreciated.
EX:
CREATE TABLE customers
(
idCustomer INT IDENTITY(100,1),
name VARCHAR(100),
PRIMARY KEY (idCustomer)
);
INSERT INTO customers
VALUES ('Bob'), ('Barb');
CREATE TABLE orders
(
idOrder INT IDENTITY(1,1),
idCustomer INT,
orderTotal DECIMAL(19,2),
orderDate DATETIME2
PRIMARY KEY (idOrder)
);
INSERT INTO orders
VALUES (100, 25.25, '2018-4-15'),
(100, 37.00, '2018-6-15'),
(100, 175.00, '2019-3-1'),
(100, 232.33, '2019-8-3'),
(101, 18.56, '2018-1-17'),
(101, 3004.50, '2018-5-12'),
(101, 2.98, '2019-6-1'),
(101, 15.00, '2019-11-3')
SELECT
c.idCustomer,
c.name,
COUNT(ord2018.idOrder) AS '#Orders 2018',
SUM(ord2018.orderTotal) AS 'Total Spent 2018'
COUNT(ord2019.idOrder) AS '#Orders 2019',
SUM(ord2019.orderTotal) AS 'Total Spent 2019'
COUNT(ordersAll.idOrder) AS '#Orders Lifetime',
SUM(ordersAll.orderTotal) AS 'Total Spent Lifetime'
FROM
customers c
JOIN
orders ord2018 ON ord2018.idCustomer = c.idCustomer
AND ord2018.orderDate > '2017-12-31'
AND ord2018.orderDate < '2019-1-1'
JOIN
orders ord2019 ON ord2019.idCustomer = c.idCustomer
AND ord2019.orderDate > '2018-12-31'
AND ord2019.orderDate < '2020-1-1'
JOIN
orders ordersAll on ordersAll.idCustomer = c.idCustomer
GROUP BY
c.idCustomer, c.name
I want to see something like this:
| idCustomer | Name | #Orders 2018 | Total Spent 2018 | #Orders 2019 | Total Spent 2019 | #Orders Lifetime | Total Spent Lifetime |
|---|---|---|---|---|---|---|---|
| 100 | Bob | 2 | 62.25 | 2 | 407.33 | 4 | 469.58 |
| 101 | Barb | 2 | 3023.06 | 2 | 17.98 | 4 | 3041.04 |
But I am getting duplicate values across the total columns which appear to just be the sum of all records in orders table per customer.
Thanks in advance.
Solution 1:[1]
For your supplied sample data and considering your example query attempt, you can use a conditional sum in conjunction with apply.
select *
from customers c
outer apply (
select
IsNull(Sum(case when Year(orderdate) = 2018 then 1 end),0) [#Orders2018],
IsNull(Sum(case when Year(orderdate) = 2018 then ordertotal end),0) [Total spent 2018],
IsNull(Sum(case when Year(orderdate) = 2019 then 1 end),0) [#Orders2019],
IsNull(Sum(case when Year(orderdate) = 2019 then ordertotal end),0) [Total spent 2019],
Count(*) TotalOrders,
Sum(Ordertotal) TotalSpend
from orders o
where o.idCustomer = c.idCustomer
)o;
- Edit, added Totals for sake of completeness :)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
