SQL counting aggregate query - sql

I have the following query:
select prop_id
, sum(amount)bnp_spent
, (select count(*) from cost where cost_type = 'Direct Cost')direct
, (select count(*) from cost where cost_type = 'Burden Cost')burden
from cost
group by prop_id
The subqueries are NOT WHAT I WANT. By selecting from the cost table I get the total number of costs that are Direct or Burden for all props
What I want is the count of direct and burden costs for each prop_id
Any help is greatly appreciated.

Try this:
select prop_id, sum(amount) as bnp_spent,
sum(case when cost_type = 'Direct Cost' then 1 else 0 end) as direct,
sum(case when cost_type = 'Burden Cost' then 1 else 0 end) as burden
from cost
group by prop_id

Related

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;

Advanced SQL with window function

I have Table a(Dimension table) and Table B(Fact table) stores transaction shopper history.
Table a : shopped id(surrogate key) created for unique combination(any of column 2,colum3,column4 repeated it will have same shopper id)
Table b is transaction data.
I am trying to identify New customers and repeated customers for each week, expected output is below.
I am thinking following SQL Statement
Select COUNT(*) OVER (PARTITION BY shopperid,weekdate) as total_new_shopperid for Repeated customer,
for Identifying new customer(ie unique) in same join condition, I am stuck on window function..
thanks,
Sam
You can use the DENSE_RANK analytical function along with aggregate function as follows:
SELECT WEEK_DATE,
COUNT(DISTINCT CASE WHEN DR = 1 THEN SHOPPER_ID END) AS TOTAL_NEW_CUSTOMER,
SUM(CASE WHEN DR = 1 THEN AMOUNT END) AS TOTAL_NEW_CUSTOMER_AMT,
COUNT(DISTINCT CASE WHEN DR > 1 THEN SHOPPER_ID END) AS TOTAL_REPEATED_CUSTOMER,
SUM(CASE WHEN DR > 1 THEN AMOUNT END) AS TOTAL_REPEATED_CUSTOMER_AMT
FROM
(
select T.*,
DENSE_RANK() OVER (PARTITION BY SHOPPER_ID ORDER BY WEEK_DATE) AS DR
FROM YOUR_TABLE T);
GROUP BY WEEK_DATE;
Cheers!!
Tejash's answer is fine (and I'm upvoting it).
However, Oracle is quite efficient with aggregation, so two levels of aggregation might have better performance (depending on the data):
select week_date,
sum(case when min_week_date = week_date then 1 else 0 end) as new_shoppers,
sum(case when min_week_date = week_date then amount else 0 end) as new_shopper_amount,
sum(case when min_week_date > week_date then 1 else 0 end) as returning_shoppers,
sum(case when min_week_date > week_date then amount else 0 end) as returning_amount
from (select shopper_id, week_date,
sum(amount) as amount,
min(week_date) over (partition by shopper_id) as min_week_date
from t
group by shopper_id, week_date
) sw
group by week_date
order by week_date;
Note: If this has better performance, it is probably due to the elimination of count(distinct).

SQL select grouping and subtract

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

Subquery returned more than 1 value in MS SQL

In MS Sql.
SELECT a.SellerID,
SUM(TransactionFee) as TransactionFees,
SUM(Quantity*a.PriceItem) as TransactionValue,
COUNT(*) as OrdersWithTransactionFees,
SUM(Quantity) as Qty,
(SELECT SUM(a.Quantity*a.PriceItem) as WholeMonthTransactionValue
from BuyProductDetails where SellerID = a.SellerID) as aa
FROM BuyProductDetails as a
WHERE MONTH(a.OrderDate)=3
AND YEAR(a.OrderDate)=2013
AND TransactionFee IS NOT NULL
GROUP BY a.SellerID
I have the above query... it can't seems to be able to run.
Basically, I have this table BuyProductDetails which stores all the orders from different Sellers.
Some orders will have TransactionFee.
Now, what I need is to calculate the total sales of these orders with TransactionFee, and the total sales for these sellers including those orders without TransactionFee.
The result set should have the following fields:
SellerID
Sum of Transaction fee
Sum of total sales
Number of Orders with Transaction fee
Qty ordered
Total sales for that seller
But when I run this sql, it returns the following error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Any help is much appreciated. Thank you.
Tried something like this ?
SELECT a.SellerID,
SUM(TransactionFee) as TransactionFees,
SUM(Quantity*a.PriceItem) as TransactionValue,
COUNT(*) as OrdersWithTransactionFees,
SUM(Quantity) as Qty,
MIN(a.WholeMonthTransactionValue) as WholeMonthTransactionValue
FROM BuyProductDetails as a,
(SELECT b.SellerID,
SUM(b.Quantity*b.PriceItem) as WholeMonthTransactionValue,
MONTH(b.OrderDate),
YEAR(b.OrderDate)
FROM BuyProductDetails b
GROUP BY b.SellerID,
MONTH(b.OrderDate) as MonthID,
YEAR(b.OrderDate) as YearID) as aa
WHERE MONTH(a.OrderDate)=3
AND YEAR(a.OrderDate)=2013
AND TransactionFee IS NOT NULL
AND a.SellerID = aa.SellerID
AND MONTH(a.OrderDate)=aa.MonthID
AND YEAR(a.OrderDate) = aa.YearID
GROUP BY a.SellerID)
You can use more effective option with CASE expression
SELECT a.SellerID,
SUM(CASE WHEN TransactionFee IS NOT NULL THEN TransactionFee END) AS TransactionFees,
SUM(CASE WHEN TransactionFee IS NOT NULL THEN Quantity * PriceItem END) AS TransactionValue,
COUNT(CASE WHEN TransactionFee IS NOT NULL THEN 1 END) as OrdersWithTransactionFees,
SUM(CASE WHEN TransactionFee IS NOT NULL THEN Quantity END) as Qty,
SUM(Quantity * PriceItem) AS WholeMonthTransactionValue
FROM BuyProductDetails AS a
WHERE MONTH(a.OrderDate) = 3 AND YEAR(a.OrderDate) = 2013
GROUP BY a.SellerID
Demo on SQLFiddle
Or merely add correct alias in the subquery
SELECT a.SellerID,
SUM(TransactionFee) as TransactionFees,
SUM(Quantity*a.PriceItem) as TransactionValue,
COUNT(*) as OrdersWithTransactionFees,
SUM(Quantity) as Qty,
(SELECT SUM(d.Quantity * d.PriceItem)
FROM BuyProductDetails d
WHERE d.SellerID = a.SellerID) as WholeMonthTransactionValue
FROM BuyProductDetails as a
WHERE MONTH(a.OrderDate)=3
AND YEAR(a.OrderDate)=2013
AND TransactionFee IS NOT NULL
GROUP BY a.SellerID
Demo on SQLFiddle

"Timeout expired" error, when executing view in SQL Server 2008

I've written a query in SQL Server 2008. The query takes about 4 minutes to execute.
I need this query as a View. So, I've created a view with this query and when I try to execute the view creation script, it shows the following error:
Timeout Expired.
The timeout period elapsed prior to completion of the operation or the server is not responding.
The query is:
SELECT t.jrnno,
(SELECT SUM(t1.amount)
FROM dbo.T_sh AS t1
WHERE (t1.b_or_s = '1') AND (t1.jrnno = t.jrnno)) AS buy,
(SELECT SUM(t2.amount)
FROM dbo.T_sh AS t2
WHERE (t2.b_or_s = '2') AND (t2.jrnno = t.jrnno)) AS sale,
SUM(t.amount) AS Total,
SUM(t.h_crg) AS Howla,
SUM(t.l_crg) AS Laga,
SUM(t.taxamt) AS Tax,
SUM(t.commsn) AS Commission
FROM dbo.T_sh AS t
WHERE (t.tran_type = 'S')
AND (t.jrnno NOT IN (SELECT DISTINCT jrnno
FROM dbo.T_ledger))
GROUP BY t.jrnno
T_sh and T_ledger both tables have about 100K rows. What could be the possible reason and how can I overcome this?
Update:
select
t.jrnno,
SUM(CASE WHEN t.b_or_s = 1 THEN t.amount ELSE NULL END) buy,
SUM(CASE WHEN t.b_or_s = 2 THEN t.amount ELSE NULL END) sale,
SUM(t.amount) AS Total,
SUM(t.h_crg) AS Howla,
SUM(t.l_crg) AS Laga,
SUM(t.taxamt) AS Tax,
SUM(t.commsn) AS Commission
FROM
dbo.t_sh t
WHERE
t.tran_type = 'S'
AND NOT EXISTS(SELECT 1 FROM dbo.T_ledger x where x.jrnno = t.jrnno)
group by
t.jrnno
It solved my problem. Thanks everyone for your quick response.
Try this query:
select
t.jrno,
SUM(CASE WHEN t1.b_or_s = 1 THEN t.amount ELSE NULL END) buy,
SUM(CASE WHEN t1.b_or_s = 2 THEN t.amount ELSE NULL END) sale,
SUM(t.amount) AS Total,
SUM(t.h_crg) AS Howla,
SUM(t.l_crg) AS Laga,
SUM(t.taxamt) AS Tax,
SUM(t.commsn) AS Commission
FROM dbo.t_sh t
WHERE t.tran_type = 'S'
AND NOT EXISTS(SELECT 1 FROM dbo.T_ledger x x.jrno = t.jrno)
Your query only needs to scan dbo.T_sh once:
SELECT t.jrnno,
SUM(CASE WHEN t.b_or_s = 1 THEN t.amount ELSE NULL END) AS buy,
SUM(CASE WHEN t.b_or_s = 2 THEN t.amount ELSE NULL END) AS sale,
SUM(t.amount) AS Total,
SUM(t.h_crg) AS Howla,
SUM(t.l_crg) AS Laga,
SUM(t.taxamt) AS Tax,
SUM(t.commsn) AS Commission
FROM dbo.T_sh AS t
WHERE t.tran_type = 'S'
AND t.jrnno NOT IN (SELECT DISTINCT
tl.jrnno
FROM dbo.T_ledger tl)
GROUP BY t.jrnno