SQL select grouping and subtract - sql

i have table named source table with data like this :
And i want to do query that subtract row with status plus and minus to be like this group by product name :
How to do that in SQL query? thanks!

Group by the product and then use a conditional SUM()
select product,
sum(case when status = 'plus' then total else 0 end) -
sum(case when status = 'minus' then total else 0 end) as total,
sum(case when status = 'plus' then amount else 0 end) -
sum(case when status = 'minus' then amount else 0 end) as amount
from your_table
group by product

There is another method using join, which works for the particular data you have provided (which has one "plus" and one "minus" row per product):
select tplus.product, (tplus.total - tminus.total) as total,
(tplus.amount - tminus.amount) as amount
from t tplus join
t tminus
on tplus.product = tminus.product and
tplus.status = 'plus' and
tplus.status = 'minus';
Both this and the aggregation query work well for the data you have provided. In other words, there are multiple ways to solve this problem (each has its strengths).

you can query as below:
select product , sum (case when [status] = 'minus' then -Total else Total end) as Total
, sum (case when [status] = 'minus' then -Amount else Amount end) as SumAmount
from yourproduct
group by product

Related

sum a value that appears on multiple rows ones per id in microsoft sql

I have a table that looks like below. In my query I'm sum:ing the order item value for each order item type, but I'm not sure how to summarize the providerfee per order id when the providerfee appears on multiple rows. Sum(providerfee) would give me 60 instead of 30.
Raw table (sample):
order id
order item type
order item value
providerfee
1
Product
300
30
1
Shipping
40
30
1
Invoicefee
30
30
Aggregated table if I would query above example table with the query I'm using now:
noOfOrders
productAmount
ShippingAmount
InvoiceAmount
providerfee
1
300
40
30
60
What value I wish to get in the providerfee column in my aggregated table instead:
noOfOrders
productAmount
ShippingAmount
InvoiceAmount
providerfee
1
300
40
30
30
Does anyone now best practice of fetching the right sum per order id from the providerfee-column? I think it won't make any sense to publish the actual query I'm writing but basically what I'm doing to fetch the amounts for order item types is:
with amounts as (
select
case when orderItemType= 'Product' then orderItemValue else 0 end as productAmount
,case when orderItemType = 'Shipping' then orderItemvalue else 0 end as shippingAmount
case when orderItemType = 'Fee' then orderItemvalue else 0 end as InvoicefeeAmount
,providerfee
from exampleTable
)
select
sum(amounts.productAmount) as productAmount
,sum(amounts.shippingAmount) as shippingAmount
,sum(amounts.invoicefeeAmount) as invoicefeeAmount
,sum(amounts.providerfee) as providerfeeAmount <---- This one gives me too high values since I'm summing every rows and providerfee appears on every row
from amounts
Here's a picture of how my actual table look like. Providerfee is supposed to be 638 just like invoiceAmount
One thing I also tried was a logic with row number function. But this gave me a result where three providerfees where missing. Instead of 638 I got 551. Can't see why since I counted in the raw table and got it to 638 myself. Not sure if I'm missing something logical with row number function that can have an impact on the SUM. Should I try another function to be able to pull out only one providerfee-row per order id?
with amounts as (
select
row_number() over (partition by orderId order by orderItemTimestamp DESC) as rn
,case when orderItemType= 'Product' then orderItemValue else 0 end as productAmount
,case when orderItemType = 'Shipping' then orderItemvalue else 0 end as shippingAmount
,case when orderItemType = 'Fee' then orderItemvalue else 0 end as InvoicefeeAmount
,providerfee
from exampleTable
)
select
sum(amounts.productAmount) as productAmount
,sum(amounts.shippingAmount) as shippingAmount
,sum(amounts.invoicefeeAmount) as invoicefeeAmount
,sum(amounts.providerfee) as providerfeeAmount <---- This one gives me too high values since I'm summing every rows and providerfee appears on every row
,sum(case when (amounts.providerfee is not null and amounts.rn = 1) then amounts.providerfee else 0 end) as providerfee2
from amounts
Grand total can be done using conditional aggregation. (Note that I here expect every Orderto have exactly one Invoicefee.)
select COUNT(distinct OrderId) as noOfOrders,
SUM(case when orderItemType = 'Product' then orderItemValue else 0 end) as productAmount,
SUM(case when orderItemType = 'Shipping' then orderItemvalue else 0 end) as shippingAmount,
SUM(case when orderItemType = 'Fee' then orderItemvalue else 0 end) as InvoicefeeAmount,
SUM(case when orderItemType = 'Fee' then providerfee else 0 end) as providerfee
from amounts
You can also add a GROUP BY, to get aggregation per order:
select OrderId,
SUM(case when orderItemType = 'Product' then orderItemValue else 0 end) as productAmount,
SUM(case when orderItemType = 'Shipping' then orderItemvalue else 0 end) as shippingAmount,
SUM(case when orderItemType = 'Fee' then orderItemvalue else 0 end) as InvoicefeeAmount,
SUM(case when orderItemType = 'Fee' then providerfee else 0 end) as providerfee
from amounts
group by OrderId

tsql - pivot sum of employee

I have here a sample table data which i want to use pivot and make my DedCode data into column.
the AMount example is already computed to its total but how can i count the number of employee if it is same with branch,deptcode and emptype.
my sample table data.
expected output:
You can use conditional aggregation:
select branch, deptcode, emptype, sum(empcount) as empcount,
sum(case when dedcode = 'PHIC' then amount else 0 end) as phic,
sum(case when dedcode = 'SLOAN' then amount else 0 end) as sloan,
sum(case when dedcode = 'VLOAN' then amount else 0 end) as vloan
from t
group by branch, deptcode, emptype;

SQL - Dividing aggregated fields, very new to SQL

I have list of line items from invoices with a field that indicates if a line was delivered or picked up. I need to find a percentage of delivered items from the total number of lines.
SALES_NBR | Total | Deliveryrate
1 = Delivered 0 = picked up from FULFILLMENT.
SELECT SALES_NBR,
COUNT (ITEMS) as Total,
SUM (case when FULFILLMENT = '1' then 1 else 0 end) as delivered,
(SELECT delivered/total) as Deliveryrate
FROM Invoice_table
WHERE STORE IN '0123'
And SALE_DATE >='2020-02-01'
And SALE_DATE <='2020-02-07'
Group By SALES_NBR, Deliveryrate;
My query executes but never finishes for some reason. Is there any easier way to do this? Fulfillment field does not contain any NULL values.
Any help would be appreciated.
I need to find a percentage of delivered items from the total number of lines.
The simplest method is to use avg():
select SALES_NBR,
avg(fulfillment) as delivered_ratio
from Invoice_table
where STORE = '0123' and
SALE_DATE >='2020-02-01' and
SALE_DATE <='2020-02-07'
group by SALES_NBR;
I'm not sure if the group by sales_nbr is needed.
If you want to get a "nice" query, you can use subqueries like this:
select
qry.*,
qry.delivered/qry.total as Deliveryrate
from (
select
SALES_NBR,
count(ITEMS) as Total,
sum(case when FULFILLMENT = '1' then 1 else 0 end) as delivered
from Invoice_table
where STORE IN '0123'
and SALE_DATE >='2020-02-01'
and SALE_DATE <='2020-02-07'
group by SALES_NBR
) qry;
But I think this one, even being ugglier, could perform faster:
select
SALES_NBR,
count(ITEMS) as Total,
sum(case when FULFILLMENT = '1' then 1 else 0 end) as delivered,
sum(case when FULFILLMENT = '1' then 1 else 0 end)/count(ITEMS) as Deliveryrate
from Invoice_table
where STORE IN '0123'
and SALE_DATE >='2020-02-01'
and SALE_DATE <='2020-02-07'
group by SALES_NBR

BigQuery: group counters by month after self-join

I have table that looks like this:
I'm trying to build a query, that will show specific partnerId counters groupped by keywordName and month.
To solve first part(without grouping by month), I've built this query:
SELECT keywordName, COUNT(keywordName) as total, IFNULL(b.ebay_count, 0) as ebay, IFNULL(c.amazon_count, 0) as amazon,
FROM LogFilesv2_Dataset.FR_Clickstats_v2 a
LEFT JOIN
(SELECT keywordName as kw , SUM(CASE WHEN partnerId='eBay' THEN 1 ELSE 0 END) as ebay_count
FROM LogFilesv2_Dataset.FR_Clickstats_v2
WHERE partnerId = 'eBay' GROUP BY kw) b
ON keywordName = b.kw
LEFT JOIN
(SELECT keywordName as kw , SUM(CASE WHEN partnerId='AmazonApi' THEN 1 ELSE 0 END) as amazon_count
FROM LogFilesv2_Dataset.FR_Clickstats_v2
WHERE partnerId = 'AmazonApi' GROUP BY kw) c
ON keywordName = c.kw
WHERE keywordName = 'flipper' -- just to filter out single kw.
GROUP BY keywordName, ebay, amazon
It works quite well and returns following output:
Now I'm trying to make additional group by month, but all my attempts returned incorrect results.
Final output supposed to be similar to this:
You can do this with conditional aggregation:
select
date_trunc(dt, month) dt,
keywordName,
count(*) total,
sum(case when partnerId = 'eBay' then 1 else 0 end) ebay,
sum(case when partnerId = 'AmazonApi' then 1 else 0 end) amazon
from LogFilesv2_Dataset.FR_Clickstats_v2
group by date_trun(dt, month), keywordName

Transact SQL - Table with different Record types requiring calculation

I have a table of invoices and Record_Types that I need to reconcile to open invoice report. I have the process down and know what I need to do. Just dont know how to properly structure the query and would prefer to not create 3 tables.
Record Types.
Invoice = 1 Credit = 5 Payment = 7
Invoice_Number, Record_Type, Dollar figure
Outstanding_Balance = Invoice(1) -(Payment(7)-(Credit))
Invoice_number Record_type Gen_Numeric_3
Basically I need to take the record_Type 1 and subtract the total of record type 7's from the below.
Invoice_Num Rec_Type Dollar_Amt
00820437 1 536.7700000000
00820437 7 469.6200000000
00820437 7 67.1500000000
Any advice would be great. messer
You can do this with aggregation and case statements:
SELECT invoice_num,
SUM(CASE WHEN rec_type = 1 THEN dollar_amt ELSE 0 END) - (SUM(CASE WHEN rec_type=7 THEN dollar_amt ELSE 0 END) - SUM(CASE WHEN rec_type=5 THEN dollar_amt ELSE 0 END)) as outstanding_balance
FROM yourtable
GROUP BY invoice_num