Divide in SQL with a where clause - sql

I need to divide where Salesman is Yes and Product is Pen over the total amount of sales (in my case is 8) and get the total percentage.
select * from mytable
Sale_Number Date Salesman_Used Product
1 01/01/2014 No Pen
2 01/02/2014 No Pen
3 01/03/2014 Yes Pen
4 01/04/2014 Yes Pencil
5 01/05/2014 Yes Pen
6 01/06/2014 Yes Pencil
7 01/07/2014 No Pencil
8 01/08/2014 No Pencil
I am stuck on the missing piece:
select concat(100 * count(missing this piece) / count(Sale_Number), '%')
as "Salesman Sales for Pens"
from mytable
where Salesman_Used = 'Yes'
and Product = 'Pen'
The problem with my attempt is that the where clause affects the Sale_Number as well.. How can I do this? Thanks in advance.

There is filter clause for an aggregates:
If FILTER is specified, then only the input rows for which the filter_clause evaluates to true are fed to the aggregate function; other rows are discarded.
So:
select concat(100 * count(*) filter (where Salesman_Used = 'Yes' and Product = 'Pen') / count(Sale_Number), '%')
as "Salesman Sales for Pens"
from mytable

You could use a subquery to get the overall count of sales entries:
select concat(100 * count(*) / (select count(*) from mytable), '%')
as "Salesman Sales for Pens"
from mytable
where Salesman_Used = 'Yes'
and Product = 'Pen'

Try this:
select concat(100 * count(missing this piece) / count(select Sale_Number from mytable), '%')
as "Salesman Sales for Pens"
from mytable
where Salesman_Used = 'Yes'
and Product = 'Pen'

I have never used Postgresql but maybe this works:
select concat(100 * (select count(*) from mytable) / count(Sale_Number), '%')
as "Salesman Sales for Pens"
from mytable
where Salesman_Used = 'Yes'
and Product = 'Pen'

Related

SUM of multi (relate to another table) rows record in another table

I have two tables an tblOrder and tblOrderDetail Table.
tblOrderDetail contain below rows:
OrderDetailID OrderID Product Quantity UnitPrice Discount Total
1 1 ABC 10 $240.00 10 $2,160.00
2 2 CDF 100 $200.00 10 $18,000.00
3 3 GHI 200 $150.00 0 $30,000.00
4 1 XYZ 40 $100.00 5 $3,800.00
i want sql query to get Subtotal column in tblOrder, which are sum of relate OrderID Total from tblOrderDetail like this:
OrderID Sub Total
1 $5,960.00
2 $18,000.00
3 $30,000.00
i try this sql query:
SELECT
OrderID
,(
SELECT
SUM(((tblOrderDetail.UnitPrice) - (tblOrderDetail.UnitPrice * (tblOrderDetail.Discount / 100))) * (tblOrderDetail.Quantity))
FROM
tblOrderDetail
WHERE tblOrderDetail.OrderID = tblOrder.OrderID
) AS [Sub Total]
FROM
tblOrder
but it gives this
OrderID Sub Total
1 $0.00
2 $0.00
3 $0.00
Note i want Sub Total column dynamically not by Sum of Total Column in tblOrderDetail Table.
I hope somebody can make sense of what I'm saying and hopefully help me achieve this!
Use Group by Clause to with SUM aggregate function,
Select *, sum(Total) as totalforOrder from ordertbl group by OrderID;
Demo SQLFiddle
as per your question, here is a correlated query
SELECT
tblOrder.OrderID
,(
SELECT
SUM(((tblOrderDetail.UnitPrice) - (tblOrderDetail.UnitPrice * (tblOrderDetail.Discount / 100))) * (tblOrderDetail.Quantity))
FROM
tblOrderDetail
WHERE tblOrderDetail.OrderID = tblOrder.OrderID
) AS SubTotal
FROM
tblOrder;
Its working fine on SQLFiddle
you can use Group by to do this
Select OrderID, sum(Total) as [Sub Total] from tblOrderDetail group by OrderID;
You can get more details here !

pgsql -Showing top 10 products's sales and other products as 'others' and its sum of sales

I have a table called "products" where it has 100 records with sales details. My requirement is so simple that I was not able to do it.
I need to show the top 10 product names with sales and other product names as "others" and its sales. so totally my o/p will be 11 rows. 11-th row should be others and sum of sales of all remaining products. Can anyone give me the logic?
O/p should be like this,
Name sales
------ -----
1 colgate 9000
2 pepsodent 8000
3 closeup 7000
4 brittal 6000
5 ariies 5000
6 babool 4000
7 imami 3000
8 nepolop 2500
9 lactoteeth 2000
10 menwhite 1500
11 Others 6000 (sum of sales of remaining 90 products)
here is my sql query,
select case when rank<11 then prod_cat else 'Others' END as prod_cat,
total_sales,ID,rank from (select ROW_NUMBER() over (order by (sum(i.grandtotal)) desc) as rank,pc.name as prod_cat,sum(i.grandtotal) as total_sales, pc.m_product_category_id as ID`enter code here`
from adempiere.c_invoice i join adempiere.c_invoiceline il on il.c_invoice_id=i.c_invoice_id join adempiere.m_product p on p.m_product_id=il.m_product_id join adempiere.m_product_category pc on pc.m_product_category_id=p.m_product_category_id
where extract(year from i.dateacct)=extract(year from now())
group by pc.m_product_category_id) innersql
order by total_sales desc
o/p what i got is,
prod_cat total_sales id rank
-------- ----------- --- ----
BSHIRT 4511697.63 460000015 1
BT-SHIRT 2725167.03 460000016 2
SHIRT 2630471.56 1000003 3
BJEAN 1793514.07 460000005 4
JEAN 1115402.90 1000004 5
GT-SHIRT 1079596.33 460000062 6
T SHIRT 446238.60 1000006 7
PANT 405189.00 1000005 8
GDRESS 396789.02 460000059 9
BTROUSER 393739.48 460000017 10
Others 164849.41 1000009 11
Others 156677.00 1000008 12
Others 146678.00 1000007 13
As #e4c5 suggests, use UNION:
select id, prod_cat, sum(total_sales) as total_sales
with
totals as (
select --pc.m_product_category_id as id,
pc.name as prod_cat,
sum(i.grandtotal) as total_sales,
ROW_NUMBER() over (order by sum(i.grandtotal) desc) as rank
from adempiere.c_invoice i
join adempiere.c_invoiceline il on (il.c_invoice_id=i.c_invoice_id)
join adempiere.m_product p on (p.m_product_id=il.m_product_id)
join adempiere.m_product_category pc on (pc.m_product_category_id=p.m_product_category_id)
where i.dateacct >= date_trunc('year', now()) and i.dateacct < date_trunc('year', now()) + interval '1' year
group by pc.m_product_category_id, pc.name
),
rankedothers as (
select prod_cat, total_sales, rank
from totals where rank <= 10
union
select 'Others', sum(total_sales), 11
from totals where rank > 10
)
select prod_cat, total_sales
from ranked_others
order by rank
Also, I recommend using sargable conditions like the one above, which is slightly more complicated than the one you implemented, but generally worth the extra effort.

Select MAX for multiple criteria in a group

Apologies if this has been answered, I'm new enough that I didn't even know how to search:
I have one table:
Lot SKU Cost Date
1001-1 1001 .30 10-12-14
1001-2 1001 .33 10-19-14
1001-3 1001 .32 11-20-14
1002-1 1002 .45 10-12-14
1002-2 1002 .45 10-19-14
1002-3 1002 .44 12-01-14
1003-1 1003 .12 10-15-14
1003-2 1003 .13 10-19-14
1003-3 1003 .10 11-23-14
i need to sum the cost of the oldest row for each SKU.
expected outcome: (.30 + .45 + .12) = .87
is this possible through one query?
ANSI SQL support a function called row_number(), which can be very helpful for this type of query. The following is how you would use it in this case:
select sum(cost)
from (select t.*, row_number() over (partition by sku order by date) as seqnum
from table t
) t
where seqnum = 1;
This should work:
select sum(t.cost)
from some_table t
join ( select sku ,
min(some_datetime_column) oldest
from some_table
and some_datetime_column is not null
group by sku
) s on s.sku = t.sku
and s.oldest = t.some_datetime_column

Multiple GROUP BY?

I'm hoping to be able to write a SQL query that can use multiple COUNTs based upon different criteria and have the values grouped together.
Let's say I have a (canned) scenario where I change the price-points of my products and want to analyze what people have paid.
SELECT Product, COUNT(*) as Total FROM Orders WHERE Location = 'Amazon'
SELECT Product, COUNT(*) as HighPriceCount FROM Orders
WHERE Location = 'Amazon' and PRICE > 10
From here, I'd like to be able to see results like this.
--------------------------------------------
| Product | Total | HighPriceCount | Avg |
--------------------------------------------
| Game 1 | 50 | 20 | .40 |
| Prod 2 | 300 | 200 | .66 |
--------------------------------------------
Where Avg. is the "price above 10" / "total sold". My initial approach is to group by Product but I wanted to see if an "inner-select" is the only path or whether there is a more elegant way to do this. Seems like a lot of duplication? Here's my initial version of a query.
-- I don't know if this works?
SELECT Product, COUNT(*) AS Total,
(
SELECT Product, COUNT(*) FROM Orders WHERE Location = 'Amazon' and Price > 10
GROUP BY Product
) AS HighPriceCount,
(Total / HighPriceCount) AS Avg
From Orders
WHERE Location = 'Amazon'
GROUP BY Product
To get the count use a CASE for HighPriceCount as below. Aggregate functions do not count null except for COUNT(*)
Sql-Fiddle Example
SELECT Product, COUNT(*) as Total,
COUNT(case when price > 10 then 1 end) as HighPriceCount,
SUM(case when price > 10 then price end)/COUNT(*) as Avg
FROM Orders
WHERE Location = 'Amazon'
GROUP BY Product
Did you try using SUM and CASE? (can't try it right know I think it should work)
SELECT PRODUCT,
SUM(CASE WHEN PRICE>10 THEN 1 ELSE 0 END) as highpricecount,
COUNT(CASE WHEN PRICE>10 THEN 1 END) as total
FROM Orders
WHERE LOCATION='AMAZON'
GROUP BY PRODUCT;
Here's mine...
Select Product, Total, HighPriceCount, HighPriceCount/Total As Avg
From (Select Product,
Sum(Case When Location = 'Amazon' Then 1 Else 0 End) As Total,
Sum(Case When Location = 'Amazon' And Price > 10 Then 1 Else 0 End) As HighPriceCount,
From Orders
Group By Product) o
Here is mine
Select
Product, Sum(Total) as Total, Sum(HighPriceCount) as HighPriceCount,Total/HighPriceCount as AVG
from
(
select Product, 1 as Total, case WHEN PRICE>10 THEN 1 ELSE 0 END as HighPriceCount
from Orders where LOCATION='AMAZON'
)
group by Product
Your query doesn't work. Please try this one:
select A.Product, A.Total, ISNULL(B.HighPriceCount,0), B.HighPriceCount*1.0/A.Total*1.0 as [Avg]
(select Product, count(*) as Total
from Orders
where Location='Amazon'
group by Product ) A
left join
(SELECT Product, COUNT(*) as HighPriceCount
from Orders
where Location = 'Amazon' and Price > 10
group by Product) B
on A.Product = B.Product
I don't have your database, so maybe there is typo, I can't test this query, but with some change by you, it should work.

Computation with different unit of measurement

I have a table like this:-
Selling Sales
Item SIZE QTY Price U/M
---- ---- ---- ----- -----
AAA 5 10 15.00 PCE
BBB 60 5 5.50 CM
CCC 8 7 12.50 PCE
DDD 75 3 6.80 CM
I need to compute the above into this using SQL:-
Item Sales Value
AAA 150.00
BBB 1,650.00
CCC 87.50
DDD 1,530.00
The problem is the Sales U/M, some in PCE (per piece) & some in CM (per centimeter).
When it's in PCE, it shd be "Selling Price * Qty" & when it's in CM, it shd be "Selling Price * Size * Qty".
How can I do this ??
Thanks.
select item, amount = case
when salesum = 'PCE'
then price * qty
else price * size * qty
end
from ...
Use a CASE:
select item,
case um
when 'PCE' then qty * price
when 'CM' then size * qty * price
end
from your_table
where um in ('PCE', 'CM');
The where clause might be over doing it a bit but you didn't specify that um could only have those two values and I'm not sure what you want to do for an "else" clause in the case.
I would do something like this.
Select Item, Case when UM='CM' then Price * Qty else Price * Qty * Size end as Value
from sellingSales
SELECT item, qty * price AS Sales_Value
FROM your_table
WHERE um = 'PCE'
UNION ALL
SELECT item, SIZE * qty * price
FROM your_table
WHERE um = 'CM';