SQL - using an alias in a where clause - where-clause

I am having trouble using an alias in my SQL:
SELECT
InvoiceDate,
BillingAddress,
BillingCity,
Total,
CASE
WHEN Total < 2.00 THEN 'Baseline Purchase'
WHEN Total BETWEEN 2.00 AND 6.99 THEN 'Low Purchase'
WHEN Total BETWEEN 7.00 AND 15.00 THEN 'Target Purchase'
ELSE 'Top Performer'
END AS PurchaseType
FROM
invoices
WHERE
PurchaseType = 'Top Performer'
ORDER BY
BillingCity
I get the following error:
Invalid column name 'PurchaseType'.

Related

Find the products contributing to the 50% of the total sales using SQL SUM window Function

There are two Tables - orders and item_line
orders
order_id
created_at
total_amount
123
2022-11-11 13:40:50
450.00
124
2022-10-30 00:40:50
1500.00
item_line
order_id
product_id
product_name
quantity
unit_price
123
a1b
milo
4
100.00
123
c2d
coke
5
10.00
124
c2d
coke
150
10.00
The question is:
Find the products contributing to the 50% of the total sales.
My take on this is -
SELECT i.product_name,SUM(o.total_amount)AS 'Net Sales'
FROM item_line i
JOIN orders o on o.order_id = i.order_id
GROUP BY i.product_name
HAVING SUM(o.total_amount) = (SUM(o.total_amount)*0.5);
But this is not correct. SUM windows functions need to be used, but how?
Try the following, explanation is within the query comments:
-- find the the total sales for each product
WITH product_sales AS
(
SELECT product_id, product_name,
SUM(quantity * unit_price) AS product_tot_sales
FROM item_line
GROUP BY product_id, product_name
),
-- find the running sales percentage for each product starting from porduct with highest sales value
running_percentage AS
(
SELECT product_id, product_name, product_tot_sales,
SUM(product_tot_sales) OVER (ORDER BY product_tot_sales DESC) /
SUM(product_tot_sales) OVER () AS running_sales_percentage,
SUM(product_tot_sales) OVER () AS tot_sales
FROM product_sales
)
-- select products that have a running sales percentage less than the min(running_sales_percentage) where running_sales_percentage >= 0.5
-- this will select all of products that contributes of 0.5 of the total sales
SELECT product_id, product_name, product_tot_sales,
tot_sales,
running_sales_percentage
FROM running_percentage
WHERE running_sales_percentage <=
(
SELECT MIN(running_sales_percentage)
FROM running_percentage
WHERE running_sales_percentage >= 0.5
)
You don't need a join with orders table, all data you need is existed in the item_line table.
See demo.

I want a query to extract the table data from SQL Server

Items table:
ItemNo, Description, BaseUnitOfMeasure, UnitPrice
-------------------------------------------------
1 Prod1 pc 200
2 prod2 pc 150
3 prod3 pc 120
ItemsLedger table:
ItemNo, Quantity
----------------
1 400
1 -20
1 -5
Above are my two tables and I want to extract the data in a format below
ItemNo, Description, BaseUnitOfMeasure, UnitPrice, Quantity
------------------------------------------------------------
1 prod1 pc 200 375
I tried this query but didn't work
SELECT
item.[No_],
item.[Description],
item.[Base Unit of Measure],
item.[Unit Price],
SUM(ledger.[Quantity])
FROM
items AS item
LEFT JOIN
ItemLedger AS ledger ON item.No_ = ledger.[Item No_]
GROUP BY
item.No_
but it didn't work. Ignore typos and table names etc.
In SQL Server, you need to include all non-aggregated columns in the GROUP BY:
SELECT i.[No_], i.[Description], i.[Base Unit of Measure], i.[Unit Price],
Sum(il.[Quantity])
FROM items i LEFT JOIN
ItemLedger as il
ON i.No_ = l.[Item No_]
GROUP BY i.[No_], i.[Description], i.[Base Unit of Measure], i.[Unit Price]

Calculate column amount and get total with order number?

How to calculate each order number amount and total amount with SQL status
Order_no Status Amount
9008258656 P 50.00
9008258656 P 0.00
9008510713 P 50.00
9008510713 P 0.00
Well, it looks like you want a simple aggregated query :
SELECT order_no, count(*) number_of_orders, sum(amount) total_amount
FROM orders
GROUP BY order_no
If you need to filter on a specific status :
SELECT order_no, count(*) number_of_orders, sum(amount) total_amount
FROM orders
WHERE status = 'P'
GROUP BY order_no
If you are looking to keep your individual line numbers (i.e. 4 total records) and not have aggregates (i.e. 2 total records), you can use the sum window function.
SELECT ord.Order_no
, ord.Status
, ord.Amount
, TotalSum = SUM(ord.Amount)OVER(PARTITION BY ord.Order_no, ord.Status)
FROM Orders ord
This would produce the following result:
Order_no Status Amount TotalAmount
9008258656 P 50.00 50.00
9008258656 P 0.00 50.00
9008510713 P 50.00 50.00
9008510713 P 0.00 50.00
Based off the example you provided, there probably is not much value in doing the sum over in this scenario. #GMB's response should suffice. However, there are a lot of cool things you can do with the sum window function such as running totals. For example, if you had an order date column, you can include after the PARTITION BY ord.Order_no, ord.Status ORDER BY ord.Order_date and this would give you a running sum of the amount that increments by each order. I.E:
Order_no Order_date Status Amount RunningTotal
9008258656 1/2/2019 P 50.00 50.00
9008258656 1/3/2019 P 0.00 50.00
9008258656 1/4/2019 P 50.00 100.00
9008258656 1/5/2019 P 0.00 100.00

Sum duplicate row values from two tables

I'm trying to get the following information from two tables in one row, but when i use group by i always get two rows:
Doc Headers
Section Doc Year Nr
SEC1 PATAG 2017 7386
Doc Lines
Section Doc Year Nr Line Type Quantity
SEC1 PATAG 2017 7386 0 1.000000
SEC1 PATAG 2017 7386 4 2.000000
Query
SELECT
cab.strCodSeccao as [Section], cab.strAbrevTpDoc as [Doc], cab.strCodExercicio
as [Year], cab.intNumero as [Nr],
Cast (SUM (lin.fltQuantidade) as NUMERIC (15,2) ) as [Quantity],
CASE WHEN lin.intTpEntPagador = 0 THEN Cast (SUM (lin.fltQuantidade) as
NUMERIC (15,2) ) ELSE 0 END as [Qtd Client],
CASE WHEN lin.intTpEntPagador = 4 THEN Cast (SUM (lin.fltQuantidade) as
NUMERIC (15,2) ) ELSE 0 END as [Qtd Warranty]
FROM
Mov_Apv_Reparacao_Lin as lin WITH (NOLOCK)
LEFT OUTER JOIN Mov_Apv_Reparacao_Cab as cab ON
(lin.strCodseccao=cab.strCodSeccao AND Cab.strAbrevTpDoc=Lin.strAbrevTpDoc AND
Cab.strCodExercicio=Lin.strCodExercicio AND Cab.intNumero=Lin.intNumero)
WHERE
cab.strAbrevTpDoc='PATAG' AND cab.strcodexercicio =
2017 and cab.intnumero = 7386
GROUP BY
cab.strCodSeccao, cab.strAbrevTpDoc, cab.strCodExercicio, cab.intNumero,
lin.intTpEntPagador
Result from Query
Section Doc Year Nr Quantity Qtd Client Qtd Warranty
SEC1 PATAG 2017 7386 1.00 1.00 0.00
SEC1 PATAG 2017 7386 2.00 0.00 2.00
Desired result
Section Doc Year Nr Quantity Qtd Client Qtd Warranty
SEC1 PATAG 2017 7386 3.00 1.00 2.00
Thanks in advance.
You have an attribute too much in your group by: you should remove lin.intTpEntPagador. That also means you have to change your case/summations:
Cast(SUM(CASE WHEN lin.intTpEntPagador = 0 THEN lin.fltQuantidade ELSE 0 END) as
NUMERIC (15,2) ) as [Qtd Client]
You should also remove the distinct, it has no function if you also group by
Try moving your SUM() outside of your CASE:
SELECT cab.strCodSeccao as [Section],
cab.strAbrevTpDoc as [Doc],
cab.strCodExercicio as [Year],
cab.intNumero as [Nr],
CAST(SUM(lin.fltQuantidade) as NUMERIC (15,2)) as [Quantity],
CAST(SUM(CASE WHEN lin.intTpEntPagador = 0
THEN lin.fltQuantidade
ELSE 0
END) AS NUMERIC (15,2)) as [Qtd Client],
CAST(SUM(CASE WHEN lin.intTpEntPagador = 4
THEN lin.fltQuantidade
ELSE 0
END) AS NUMERIC (15,2)) as [Qtd Warranty]
Side note, no need for DISTINCT here when you already have a GROUP BY

Get the Data horizontally rather than vertically

Consider the query :
Select Dealer, Sales from DEALERDATA
where period in (201106,201107)
This will give result as:
DEALER SALES
Dealer1 100000
Dealer1 200000
Dealer2 600000
Dealer2 700000
I want result as
DEALER SALES SALES
Dealer1 100000 200000
Dealer2 600000 700000
If any one can let me know how this can be achieved?
Many thanks,
Sharon....
For a few number of columns you can use CASE combined WITH sum
SELECT Dealer
, SUM(CASE WHEN period=201106 THEN Sales ELSE 0 END) sales201106
, SUM(CASE WHEN period=201107 THEN Sales ELSE 0 END) sales201107
FROM DEALERDATA
WHERE period IN (201106,201107)
GROUP BY Dealer