Reputation: 143
This is probably easier than I think it is, but I am stumped. I wrote the following query which sums up all the purchases made by a customer at a particular store, as well as the total amount of returns made by the same customer at the same store, and lastly, stores the result of subtracting total returns from total purchases in a calculated column called TOTAL_SPENT. Here is my query:
SELECT Account_Id,
SUM(CASE WHEN Transaction_Code = 'Purchase' THEN Transaction_Amount ELSE 0 END) AS TOTAL_PURCHASED,
SUM(CASE WHEN Transaction_Code = 'Return' THEN Transaction_Amount ELSE 0 END) AS TOTAL_RETURNED,
(TOTAL_PURCHASED - TOTAL_RETURNED) AS TOTAL_SPENT
FROM Transactions_Table
WHERE Store = 'Store XYZ'
GROUP BY Account_Id
ORDER BY TOTAL_SPENT DESC
My problem is that this query returns hundreds of thousands of records, but I only care about approximately 10% of the data that's returned. So, say you only want to see data returned where TOTAL_SPENT >= 500.00. But for the life of me, I cannot figure out how to do this! hanging head in shame
Upvotes: 0
Views: 59
Reputation: 91696
In SQL, the WHERE
clause is processed before the SELECT
clause. So, when SQL begins filtering the rows from your table that are relevent to your query, it doesn't yet know about the column TOTAL_SPENT
.
There's a few ways to fix that.
1) Repeat the expressions in your WHERE
clause, rather than referring to a column name in your SELECT
clause:
SELECT Account_Id,
SUM(CASE WHEN Transaction_Code = 'Purchase' THEN Transaction_Amount ELSE 0 END) AS TOTAL_PURCHASED,
SUM(CASE WHEN Transaction_Code = 'Return' THEN Transaction_Amount ELSE 0 END) AS TOTAL_RETURNED,
(TOTAL_PURCHASED - TOTAL_RETURNED) AS TOTAL_SPENT
FROM Transactions_Table
WHERE Store = 'Store XYZ'
GROUP BY Account_Id
ORDER BY
(SUM(CASE WHEN Transaction_Code = 'Purchase' THEN Transaction_Amount ELSE 0 END) - SUM(CASE WHEN Transaction_Code = 'Return' THEN Transaction_Amount ELSE 0 END)) DESC
Note: If you're looking to find groups with a TOTAL_SPENT
above 500, use the HAVING
clause instead of WHERE
.
2) Use a view. Remove your WHERE
clause and create a VIEW
with your query. Then, select from that view and add your WHERE
clause.
CREATE VIEW Whatever AS
SELECT Account_Id,
SUM(CASE WHEN Transaction_Code = 'Purchase' THEN Transaction_Amount ELSE 0 END) AS TOTAL_PURCHASED,
SUM(CASE WHEN Transaction_Code = 'Return' THEN Transaction_Amount ELSE 0 END) AS TOTAL_RETURNED,
(TOTAL_PURCHASED - TOTAL_RETURNED) AS TOTAL_SPENT
FROM Transactions_Table
GROUP BY Account_Id;
SELECT * From Whatever WHERE TOTAL_SPENT >= 500
3) Use a nested SELECT:
select * from (
SELECT
Account_Id,
SUM(CASE WHEN Transaction_Code = 'Purchase' THEN Transaction_Amount ELSE 0 END) AS TOTAL_PURCHASED,
SUM(CASE WHEN Transaction_Code = 'Return' THEN Transaction_Amount ELSE 0 END) AS TOTAL_RETURNED,
(TOTAL_PURCHASED - TOTAL_RETURNED) AS TOTAL_SPENT
FROM Transactions_Table
WHERE Store = 'Store XYZ'
GROUP BY Account_Id
) where TOTAL_SPENT > 500 ORDER BY TOTAL_SPENT DESC;
4) If your database supports it, use a CTE:
WITH MyQuery AS (
SELECT
Account_Id,
SUM(CASE WHEN Transaction_Code = 'Purchase' THEN Transaction_Amount ELSE 0 END) AS TOTAL_PURCHASED,
SUM(CASE WHEN Transaction_Code = 'Return' THEN Transaction_Amount ELSE 0 END) AS TOTAL_RETURNED,
(TOTAL_PURCHASED - TOTAL_RETURNED) AS TOTAL_SPENT
FROM Transactions_Table
WHERE Store = 'Store XYZ'
GROUP BY Account_Id
)
SELECT * FROM MyQuery WHERE TOTAL_SPENT > 500 ORDER BY TOTAL_SPENT DESC;
Upvotes: 1