Is a better way to join theses subqueries? - sql

I have the results I required, however there must be a more efficient way to do this. I looked at a pivot, but that would not help me. Suggestions welcome!
SELECT GL1.CashPosition,
GL2.ARBalance,
GL3.APBalance,
GL4.LineOfCredit
FROM
(
Select GLAccounts.CurrencyCodeID,
SUM(GLAccounts.PostedBalance + GLAccounts.UnPostedBalance) AS CashPosition
FROM GLAccounts
WHERE GLAccounts.GLAccountID IN(1,3)
GROUP BY GLAccounts.CurrencyCodeID
) AS GL1
JOIN
(
Select GLAccounts.CurrencyCodeID,
SUM(GLAccounts.PostedBalance + GLAccounts.UnPostedBalance) AS ARBalance
FROM GLAccounts
WHERE GLAccounts.GLAccountID IN(5,6,7,9,10,11,12)
GROUP BY GLAccounts.CurrencyCodeID
) AS GL2
JOIN
(
Select GLAccounts.CurrencyCodeID,
SUM(GLAccounts.PostedBalance + GLAccounts.UnPostedBalance) AS APBalance
FROM GLAccounts
WHERE GLAccounts.GLAccountID IN(108,109)
GROUP BY GLAccounts.CurrencyCodeID
) AS GL3
JOIN
(
Select GLAccounts.CurrencyCodeID,
SUM(GLAccounts.PostedBalance + GLAccounts.UnPostedBalance) AS LineOfCredit
FROM GLAccounts
WHERE GLAccounts.GLAccountID IN(139,140)
GROUP BY GLAccounts.CurrencyCodeID
)AS GL4 ON GL3.CurrencyCodeID = GL4.CurrencyCodeID ON GL2.CurrencyCodeID
= GL3.CurrencyCodeID ON GL1.CurrencyCodeID = GL2.CurrencyCodeID

You can use case when:
SELECT
SUM(CASE WHEN GLAccounts.GLAccountID IN (1,3)
THEN GLAccounts.PostedBalance + GLAccounts.UnPostedBalance ELSE 0 END) AS CashPosition,
SUM(CASE WHEN GLAccounts.GLAccountID IN (5,6,7,9,10,11,12)
THEN GLAccounts.PostedBalance + GLAccounts.UnPostedBalance ELSE 0 END) AS ARBalance,
SUM(CASE WHEN GLAccounts.GLAccountID IN (108,109)
THEN GLAccounts.PostedBalance + GLAccounts.UnPostedBalance ELSE 0 END) AS APBalance,
SUM(CASE WHEN GLAccounts.GLAccountID IN (139,140)
THEN GLAccounts.PostedBalance + GLAccounts.UnPostedBalance ELSE 0 END) AS LineOfCredit
FROM GLAccounts

Not necessarily an efficiency improvement, but I would suggest turning the subquery into a stored proc to neaten the code.

You can case inside a sum
SELECT
SUM(CASE WHEN GLAccounts.GLAccountID IN (1,3) THEN GLAccounts.PostedBalance + GLAccounts.UnPostedBalance ELSE 0 END) AS CashPosition,
SUM(CASE WHEN GLAccounts.GLAccountID IN (5,6,7,9,10,11,12) THEN GLAccounts.PostedBalance + GLAccounts.UnPostedBalance ELSE 0 END) AS ARBalance,
SUM(CASE WHEN GLAccounts.GLAccountID IN (108,109) THEN GLAccounts.PostedBalance + GLAccounts.UnPostedBalance ELSE 0 END) AS APBalance,
SUM(CASE WHEN GLAccounts.GLAccountID IN (139,140) THEN GLAccounts.PostedBalance + GLAccounts.UnPostedBalance ELSE 0 END) AS LineOfCredit
FROM GLAccounts

You can use a conditional sum using case expressions. This avoids repeatedly hitting the same table multiple times and significantly reduces your logical reads:
select
Sum(case when GLAccountID in(1,3) then GLAccounts.PostedBalance + GLAccounts.UnPostedBalance end) as CashPosition,
Sum(case when GLAccountID in(5,6,7,9,10,11,12) then GLAccounts.PostedBalance + GLAccounts.UnPostedBalance end) as ARBalance,
Sum(case when GLAccountID in(108,109) then GLAccounts.PostedBalance + GLAccounts.UnPostedBalance end) as APBalance,
Sum(case when GLAccountID in(139,140) then GLAccounts.PostedBalance + GLAccounts.UnPostedBalance end) as LineOfCredit
from GLAccounts

Related

Combine Table in SQL

I have two tables would like to combine.
I would like the table will automatically add a row for image2 when there are new generalname in image1.
select B.Trsdate, count(B.Billno) As Billno, sum(B.pax) As Pax, sum(B.Grossamount) As GrossAmount, sum(B.discountamount) As Discount, sum(B.taxamount) As Tax, sum(B.servicechargeamount) As SCharge, sum(B.nettamount) As NettAmt, sum(B.rounddiff) As RDiff, sum(B.roundamt) As RoundAmt, sum(B.reversalYN) As RevBillNo, SUM(GD.CASH) AS 'P_CASH', SUM(GD.VISA) AS 'P_VISA', SUM(GD.MASTER) AS 'P_MASTER', SUM(GD.AMEX) AS 'P_Amex', SUM(GD.CityLedger) AS 'P_CityLedger', SUM(GD.OtherPayment) As 'P_Other'
from vpos_eod_bills As B
INNER JOIN
(
SELECT TrsNo,SUM(CASH) as CASH,SUM(Visa) as Visa, SUM(Master) as Master, SUM(Amex) AS Amex, SUM(CityLedger) as CityLedger, SUM(OtherPayment) as OtherPayment, SUM(Total) as Total FROM
(
select TrsNo, GENERALNAME,
(case WHEN(Generalname IN ('CASH'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'CASH',
(case WHEN(Generalname IN ('VISA'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'Visa',
(case WHEN(Generalname IN ('MASTER'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'Master',
(case WHEN(Generalname IN ('AMEX'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'Amex',
(case WHEN(Generalname = 'City Ledger' OR Generalname = 'CREDIT A/C' OR Generalname = 'BOSS' OR Generalname = 'ENTERTAINMENT')
THEN
SUM(AMOUNT)
ELSE
0
END) as 'CityLedger',
(case WHEN(Generalname not IN ('CASH','Voucher','VISA','MASTER','AMEX','JCB','City Ledger','CREDIT A/C','BOSS','ENTERTAINMENT') and (Generalname not like '%card%') and (Generalname not like '%Coupon%') and (Generalname not like '%GROUPON%') and (Generalname not like '%COURSE%'))
THEN
SUM(AMOUNT)
ELSE
0
END) as 'OtherPayment',
SUM(AMOUNT) as Total
from Vpos_eod_GeneralDetails
where BillType = 'P'
group by TrsNo, GeneralName
) As A
Group By A.trsno
)As GD ON GD.TrsNo = B.TrsNo
where B.PaidStatus = '1' and B.VoidStatus = '0' and (B.trsdate between '20200101' and '20200131')
group by B.trsdate

Subquery to pull sum amount from different table and group by salesperson

--I am trying to simply add one subquery to take the total sales of each salesperson in relation to their quotes. I am at a loss and hopefully someone can help.
select sp.FIRST_NAME + ' ' + sp.LAST_NAME,
sum(case when sq.SAL_QUOTE_STATUS_ID = '1' then 1 else 0 end) as [Created],
sum(case when sq.SAL_QUOTE_STATUS_ID = '4' then 1 else 0 end) as [Ordered],
sum(case when sq.SAL_QUOTE_STATUS_ID = '3' then 1 else 0 end) as [Rejected],
sum(sq.AMOUNT_INCLUDING_TAX) as [Amount],
sum(sq.COST) as [Cost],
sum(sq.AMOUNT_INCLUDING_TAX - sq.COST) as [Profit],
round(100 * (case when sum(sq.AMOUNT_INCLUDING_TAX) > 0 then
(sum(sq.AMOUNT_INCLUDING_TAX) -
sum(sq.COST)) / sum(sq.AMOUNT_INCLUDING_TAX) else 0 end), 3) as [GP%],
(Select sum(so.amount_including_tax)
from SAL_SALES_ORDER so
where so.SALESPERSON_ID = sp.SALESPERSON_ID) as [YTD Sales]
from SAL_SALES_QUOTE sq
inner join CRM_SALESPERSON sp on sp.SALESPERSON_ID = sq.SALESPERSON_ID
where sq.CREATED_DATE > '01-01-2018'
group by sp.FIRST_NAME + ' ' + sp.LAST_NAME
I took your subquery out of the select, made it into a result set to join on , and then pulled the sum from there.
select sp.FIRST_NAME + ' ' + sp.LAST_NAME,
sum(case when sq.SAL_QUOTE_STATUS_ID = '1' then 1 else 0 end) as [Created],
sum(case when sq.SAL_QUOTE_STATUS_ID = '4' then 1 else 0 end) as [Ordered],
sum(case when sq.SAL_QUOTE_STATUS_ID = '3' then 1 else 0 end) as [Rejected],
sum(sq.AMOUNT_INCLUDING_TAX) as [Amount],
sum(sq.COST) as [Cost],
sum(sq.AMOUNT_INCLUDING_TAX - sq.COST) as [Profit],
round(100 * (case when sum(sq.AMOUNT_INCLUDING_TAX) > 0 then
(sum(sq.AMOUNT_INCLUDING_TAX) -
sum(sq.COST)) / sum(sq.AMOUNT_INCLUDING_TAX) else 0 end), 3) as [GP%],
sum([x.ytd_sales]) AS YTD_Sales
from SAL_SALES_QUOTE sq
inner join CRM_SALESPERSON sp on sp.SALESPERSON_ID = sq.SALESPERSON_ID
inner join (Select so.salesperson_id, sum(so.amount_including_tax) AS [YTD Sales]
from SAL_SALES_ORDER so
group by so.salesperson_id) x
ON x.salesperson_id = sp.salesperson_id
where sq.CREATED_DATE > '01-01-2018'
group by sp.FIRST_NAME + ' ' + sp.LAST_NAME

Update a complex SQL query to add a new column with the sum of two columns

The below SQL query creates a table with n number of columns named in the next line.
...., curr_amount, tax_amount, ....
I am having a very tough time updating the below query to create a new column called total and position it exactly after tax_amount column and the total column should contain the values that are obtained after sum of curr_amount & tax_amount.
I have been working on this from more than one day but couldn't figure it out.
P.S. Still a noob here. Thanks alot for your time.
.
SELECT Isnull(t.total_month, 'Total') total_month,
t.tax_amount,
t.curr_amount,
t.usage_qty,
t.kh_qty,
t.bill_cnt
FROM (SELECT dbo.Sigmadf(bm.posted_date, 'YYYY-MM') total_month,
Sum(CASE
WHEN rr.usage_qty IS NULL THEN 0
ELSE Cast (rr.usage_qty AS NUMERIC(18, 2))
END) usage_qty,
Sum(CASE
WHEN bm.curr_amount IS NULL THEN 0
ELSE bm.curr_amount
END) curr_amount,
Sum(CASE
WHEN bm.adj_amount IS NULL THEN 0
ELSE bm.adj_amount
END) adj_amount,
Sum(CASE
WHEN bm.bal_fwd_amount IS NULL THEN 0
ELSE bm.bal_fwd_amount
END) bal_forward,
Sum(CASE
WHEN bm.tax_amount IS NULL THEN 0
ELSE bm.tax_amount
END) tax_amount,
Sum(CASE
WHEN bm.due_amount IS NULL THEN 0
ELSE bm.due_amount
END) due_amount,
Sum(CASE
WHEN bm.last_total_paid_amount IS NULL THEN 0
ELSE bm.last_total_paid_amount * -1
END) paid_amount,
Sum(CASE
WHEN bm.bill_print = 'Y' THEN 1
ELSE 0
END) pdf_cnt,
Sum(CASE
WHEN Isnull(bm.bill_handling_code, '0') = '0' THEN 1
ELSE 0
END) reg_cnt,
Sum(CASE
WHEN Isnull(bm.bill_handling_code, '0') = '1' THEN 1
ELSE 0
END) ftime_cnt,
Sum(CASE
WHEN Isnull(bm.bill_handling_code, '0') = '9999' THEN 1
ELSE 0
END) ltime_cnt,
Count(*) bill_cnt,
Sum(CASE
WHEN bill_status = '01' THEN 1
ELSE 0
END) canc_cnt,
Sum(CASE
WHEN bill_status = '01' THEN
CASE
WHEN rr.usage_qty IS NULL THEN 0
ELSE Cast (rr.usage_qty AS NUMERIC(18, 2))
END
ELSE 0
END) canc_usg,
Sum(CASE
WHEN vis.kh_qty IS NULL THEN 0
ELSE Cast(vis.kh_qty AS NUMERIC(18, 2))
END) kh_qty
FROM bill_master bm WITH (nolock)
INNER JOIN (SELECT bill_no,
Sum(CASE
WHEN vpb.recurr_charge_type IN ( 'T4',
'SLF' )
THEN
CASE
WHEN vpb.print_qty = 'Y'
AND vpb.usage_qty IS NOT NULL
THEN
Cast (vpb.usage_qty AS
NUMERIC(18, 2))
ELSE 0
END
ELSE 0
END) usage_qty
FROM v_print_bills_all vpb
GROUP BY bill_no) rr
ON rr.bill_no = bm.bill_no
LEFT OUTER JOIN vis_bill_master_cr vis WITH (nolock)
ON bm.bill_no = vis.bill_no
WHERE 1 = 1
AND dbo.Trunc(bm.posted_date) >= '20150101'
AND dbo.Trunc(bm.posted_date) <= '20151124'
AND bm.posted_date IS NOT NULL
AND bm.cust_id NOT IN (SELECT cc.code_type cust_id
FROM code_table cc WITH (nolock)
WHERE cc.code_tabname = 'RptExclCust'
AND cc.code_value = 'cust_id')
GROUP BY dbo.Sigmadf(bm.posted_date, 'YYYY-MM') WITH rollup)t
I must say that the explanation is not so clear.
From my understanding, you want the total of two columns.
So, wrap all your query between parenthesis, call it subQuery, and make the sum of the two columns on top:
SELECT subQuery.total_month as bill_date,
subQuery.curr_amount as amount,
subQuery.tax_amount tax,
subQuery.curr_amount + subQuery.tax_amount as [total],
...
FROM
(..your entire query here..) as subQuery

SQL QUERY case with a condition

I have a sql query where I have to get records count, I am getting counts correctly with the current query but I want to only get counts for records where 'Unchecked Count' is not zero.
SELECT
dbo.Customer.AccountNo AS Cust_Acc_No,
dbo.Customer.Name AS [Customer Name],
dbo.Customer.Adrs1 AS Cust_Address_1,
dbo.Customer.Adrs2 AS Cust_Address_2,
dbo.Customer.City AS Cust_City,
dbo.Customer.Province,
dbo.Customer.PostalCode AS Cust_Postal_Code,
dbo.Customer.Email1 AS Email,
CAST(dbo.Customer.AccStatus AS int) AS [Account Status],
dbo.Customer.ID AS CID,
case when COUNT(dbo.Manifest.ID) <
sum( CASE WHEN (dbo.Manifest.CheckedBy IS NULL OR
(LTRIM(RTRIM(dbo.Manifest.CheckedBy)) = '')) THEN 1 ELSE 0 END)
then COUNT(dbo.Manifest.ID) else
sum( CASE WHEN (dbo.Manifest.CheckedBy IS NULL OR
(LTRIM(RTRIM(dbo.Manifest.CheckedBy)) = '')) THEN 1 ELSE 0 END)
end as [Unchecked Count],
case when COUNT(dbo.Manifest.ID) <
sum( CASE WHEN (dbo.Manifest.CheckedBy IS not NULL OR
(LTRIM(RTRIM(dbo.Manifest.CheckedBy))! = '')) THEN 1 ELSE 0 END)
then COUNT(dbo.Manifest.ID) else
sum( CASE WHEN (dbo.Manifest.CheckedBy IS not NULL OR
(LTRIM(RTRIM(dbo.Manifest.CheckedBy))! = '')) THEN 1 ELSE 0 END)
end as [Checked_Count],
COUNT(dbo.Manifest.ID) as Total
FROM
dbo.Customer inner JOIN dbo.Manifest ON dbo.Customer.AccountNo = dbo.Manifest.FKAccountNo
GROUP BY
dbo.Customer.AccountNo,
dbo.Customer.Name,
dbo.Customer.Adrs1,
dbo.Customer.City,
dbo.Customer.Province,
dbo.Customer.Adrs2,
dbo.Customer.Email1,
dbo.Customer.PostalCode,
dbo.Customer.AccStatus,
dbo.Customer.ID,Manifest.FKAccountNo
Try Having clause after your group by clause
having [Unchecked Count] > 0
Full query
SELECT dbo.Customer.AccountNo AS Cust_Acc_No, dbo.Customer.Name AS [Customer Name], dbo.Customer.Adrs1 AS Cust_Address_1, dbo.Customer.Adrs2 AS Cust_Address_2, dbo.Customer.City AS Cust_City,
dbo.Customer.Province, dbo.Customer.PostalCode AS Cust_Postal_Code, dbo.Customer.Email1 AS Email, CAST(dbo.Customer.AccStatus AS int) AS [Account Status], dbo.Customer.ID AS CID,
case when COUNT(dbo.Manifest.ID) < sum( CASE WHEN (dbo.Manifest.CheckedBy IS NULL OR
(LTRIM(RTRIM(dbo.Manifest.CheckedBy)) = '')) THEN 1 ELSE 0 END)
then COUNT(dbo.Manifest.ID) else
sum( CASE WHEN (dbo.Manifest.CheckedBy IS NULL OR
(LTRIM(RTRIM(dbo.Manifest.CheckedBy)) = '')) THEN 1 ELSE 0 END)
end
as [Unchecked Count],
case when COUNT(dbo.Manifest.ID) < sum( CASE WHEN (dbo.Manifest.CheckedBy IS not NULL OR
(LTRIM(RTRIM(dbo.Manifest.CheckedBy))! = '')) THEN 1 ELSE 0 END)
then COUNT(dbo.Manifest.ID) else
sum( CASE WHEN (dbo.Manifest.CheckedBy IS not NULL OR
(LTRIM(RTRIM(dbo.Manifest.CheckedBy))! = '')) THEN 1 ELSE 0 END)
end
as [Checked_Count],
COUNT(dbo.Manifest.ID) as Total
FROM dbo.Customer inner JOIN
dbo.Manifest ON dbo.Customer.AccountNo = dbo.Manifest.FKAccountNo
GROUP BY dbo.Customer.AccountNo, dbo.Customer.Name, dbo.Customer.Adrs1, dbo.Customer.City, dbo.Customer.Province, dbo.Customer.Adrs2, dbo.Customer.Email1, dbo.Customer.PostalCode, dbo.Customer.AccStatus,
dbo.Customer.ID,Manifest.FKAccountNo
having [Unchecked Count] > 0
You can query the result of the other query.
SELECT * FROM ( <your query> ) AS T WHERE [Unchecked Count] > 0
Thank you AlexanderW and Shakti for your answers.I tried both of your suggestions but 'Unchecked Count' is a alias, that is why I was getting 'invalid Column error'. But your answers helped me to solve the problem. Here is how it is working now, please let me know if you have better suggestion/s..
WITH OnlyUnchecked AS(<MyQuery>)
SELECT *
FROM OnlyUnchecked
WHERE [Unchecked Count]>0

SQL Query to Calculate two Amounts on the same row

probably a very simple answer but i'm new to T-SQL so could do with some help!
I need a 3rd column that works out TotInc - (minus) TotEx to give me a TotalDisposableIncome
Here is my SQL:
--This gives me the Total Income and Total Expenditure on the same row
SELECT
SUM(CASE WHEN Type = '1' THEN Amount ELSE 0 END) as TotalInc,
SUM(CASE WHEN Type = '2' THEN Amount ELSE 0 END) as TotEx
FROM ClaimFinancials
Thanks!
You could use a Common Table Expression (CTE):
WITH T1 AS
(
SELECT
SUM(CASE WHEN Type = '1' THEN Amount ELSE 0 END) as TotalInc,
SUM(CASE WHEN Type = '2' THEN Amount ELSE 0 END) as TotEx
FROM ClaimFinancials
)
SELECT TotalInc, TotEx, TotalInc - TotEx AS TotalDisposableIncome
FROM T1
Or an ordinary subquery:
SELECT TotalInc, TotEx, TotalInc - TotEx AS TotalDisposableIncome
FROM
(
SELECT
SUM(CASE WHEN Type = '1' THEN Amount ELSE 0 END) as TotalInc,
SUM(CASE WHEN Type = '2' THEN Amount ELSE 0 END) as TotEx
FROM ClaimFinancials
) T1
You can't reference your column aliases elsewhere in your SELECT clause. Here is one alternative.
SELECT TotalInc, TotEx, TotInc - TotEx as TotalDisposable
FROM (
SELECT
SUM(CASE WHEN Type = '1' THEN Amount ELSE 0 END) as TotalInc,
SUM(CASE WHEN Type = '2' THEN Amount ELSE 0 END) as TotEx
FROM ClaimFinancials
) AS Total
There's more than one way to do it.
WITH T1 AS
(
SELECT
Type,
SUM(Amount as Total
FROM ClaimFinancials
)
SELECT
Inc.Total as TotalInc,
Ex.Total as TotEx,
Inc.Total - Ex.Total AS TotalDisposableIncome
FROM T1 Inc, T2 Ex
where T1.Type = 1 and T2.Type = 2
SELECT
SUM(CASE WHEN Type = '1' THEN Amount ELSE 0 END) as TotalInc,
SUM(CASE WHEN Type = '2' THEN Amount ELSE 0 END) as TotEx,
SUM(CASE
WHEN Type = '1' THEN Amount
WHEN Type = '2' Then -Amount
ELSE 0
END) AS TotalDisposableIncome
FROM ClaimFinancials