How to add 2 numbers in sql Select clause? - sql

I have this query:
Select
Count(DocumentID)
From
Documents d
Inner Join
Accounts a on a.AccountID = d.CreatedByAccountID
Where
a.FeeExempt = 1
Or
(Select
Case
When a.OrganizationTypeID = 1 Or a.OrganizationTypeID = 2
Then 0
Else EFileFee
End
From ITypes
Where ITypeID = d.ITypeID
+
Select 100 --just to test
) <= 0
How can I make this query compile? Basically I want to do 2 selects and check if addition of both of them is less than 0 or not. But obviously at the moment the query is incorrect and won't compile.

Do you want this:
. . ..
(select sum(val)
from ((Select (Case When a.OrganizationTypeID = 1 Or a.OrganizationTypeID = 2 Then 0 Else EFileFee End) as val
From ITypes
Where ITypeID = d.ITypeID
) union all
(Select 100 --just to test
)
) t
) <= 0

Related

The SQL Server query is taking too long to load the data

The below query is actually a view which is being used to display the cash payment report. But it is taking too much of time to load the data
SELECT
Billing_AccountPaymentDate.DueDate,
SUM(Billing_AccountCharge.NetAmount) AS NetCharges,
ISNULL(SUM(AccountChargePayment.SchoolPayments + AccountChargePayment.SchoolRemittances + AccountChargePayment.SchoolRemittancesPending), 0) / SUM(Billing_AccountCharge.NetAmount) AS PercentCollected,
SUM(Billing_AccountCharge.NetAmount - ISNULL(AccountChargePayment.SchoolPayments + AccountChargePayment.SchoolRemittances + AccountChargePayment.SchoolRemittancesPending, 0)) AS RemainingBalance,
Billing_AccountPaymentDate.RemittanceEffectiveDate,
Billing_Account.SchoolId,
ISNULL(SUM(AccountChargePayment.SchoolPayments), 0) AS SchoolPayments,
ISNULL(SUM(AccountChargePayment.SchoolRemittances), 0) AS SchoolRemittances,
ISNULL(SUM(AccountChargePayment.SchoolRemittancesPending), 0) AS SchoolRemittancesPending,
Billing_Account.SchoolYearId,
ISNULL(SUM(AccountChargePayment.SchoolPayments + AccountChargePayment.SchoolRemittances), 0) AS TotalReceipts
FROM
Billing_AccountCharge
INNER JOIN
Billing_AccountInvoice ON
Billing_AccountInvoice.AccountInvoiceId = Billing_AccountCharge.AccountInvoiceId
INNER JOIN
Billing_Account ON
Billing_Account.AccountId = Billing_AccountInvoice.AccountId
INNER JOIN
Billing_PaymentMethod ON
Billing_PaymentMethod.PaymentMethodId = CASE WHEN Billing_AccountInvoice.AutomaticPaymentEligible = 1 THEN Billing_Account.PaymentMethodId ELSE 3 END -- Send Statements
INNER JOIN
Billing_AccountPaymentDate ON
Billing_AccountPaymentDate.AccountPaymentMethodId = Billing_PaymentMethod.AnticipatedAccountPaymentMethodId AND
Billing_AccountPaymentDate.DueDate = Billing_AccountInvoice.DueDate AND
Billing_AccountPaymentDate.HoldForFee = Billing_Account.HoldPaymentForFee
INNER JOIN
Billing_ChargeItem ON
Billing_ChargeItem.ChargeItemId = Billing_AccountCharge.ChargeItemId
LEFT OUTER JOIN
(
SELECT
Billing_AccountChargePayment.AccountChargeId,
SUM(CASE WHEN Billing_AccountPayment.AccountPaymentTypeId = 9 THEN Billing_AccountChargePayment.Amount ELSE 0 END) AS SchoolPayments,
SUM(CASE WHEN Billing_AccountChargePayment.SchoolRemittanceId IS NOT NULL THEN Billing_AccountChargePayment.Amount ELSE 0 END) AS SchoolRemittances,
SUM(CASE WHEN Billing_AccountChargePayment.SchoolRemittanceId IS NULL AND Billing_AccountPayment.AccountPaymentTypeId <> 9 THEN Billing_AccountChargePayment.Amount ELSE 0 END) AS SchoolRemittancesPending
FROM
Billing_AccountChargePayment
INNER JOIN
Billing_AccountPayment ON
Billing_AccountPayment.AccountPaymentId = Billing_AccountChargePayment.AccountPaymentId
GROUP BY
Billing_AccountChargePayment.AccountChargeId
) AccountChargePayment ON
AccountChargePayment.AccountChargeId = Billing_AccountCharge.AccountChargeId
WHERE
Billing_AccountInvoice.AccountInvoiceStatusId <> 4 AND -- Voided
Billing_ChargeItem.RemitToSchool = 1
AND Billing_Account.[SchoolId] = 6 --hard code in a school with data
AND Billing_Account.[SchoolYearId] = 12 --hard code in a school year with data
GROUP BY
Billing_AccountPaymentDate.DueDate,
Billing_AccountPaymentDate.RemittanceEffectiveDate,
Billing_Account.SchoolId,
Billing_Account.SchoolYearId
HAVING
SUM(Billing_AccountCharge.NetAmount) <> 0
order by Billing_AccountPaymentDate.DueDate ASC
It looks like the inner query in the left join is taking too much of time, both the tables already have non clustered index, I tried taking those tables outside but the data is not accurate
Use CTE instead of subquery and do all calculation there instead of in Left outer join. Moreover, use with(nolock) whenever you fetch data. Still your query is taking much more time then You should implement proper indexing.
WITH PaymentData AS (
SELECT
acp.AccountChargeId,
SUM(
CASE
WHEN ap.AccountPaymentTypeId = 9 THEN acp.Amount
ELSE 0
END
) AS SchoolPayments,
SUM(
CASE
WHEN acp.SchoolRemittanceId IS NOT NULL THEN acp.Amount
ELSE 0
END
) AS SchoolRemittances,
SUM(
CASE
WHEN acp.SchoolRemittanceId IS NULL AND ap.AccountPaymentTypeId <> 9 THEN acp.Amount
ELSE 0
END
) AS SchoolRemittancesPending
FROM
Billing_AccountChargePayment acp WITH(NOLOCK)
INNER JOIN Billing_AccountPayment ap WITH(NOLOCK) ON acp.AccountPaymentId = ap.AccountPaymentId
GROUP BY
acp.AccountChargeId
)
SELECT
apd.DueDate,
SUM(ac.NetAmount) AS NetCharges,
COALESCE(
SUM(pd.SchoolPayments + pd.SchoolRemittances + pd.SchoolRemittancesPending),
0
) / SUM(ac.NetAmount) AS PercentCollected,
SUM(ac.NetAmount - COALESCE(pd.SchoolPayments, 0) - COALESCE(pd.SchoolRemittances, 0) - COALESCE(pd.SchoolRemittancesPending, 0)) AS RemainingBalance,
apd.RemittanceEffectiveDate,
a.SchoolId,
COALESCE(SUM(pd.SchoolPayments), 0) AS SchoolPayments,
COALESCE(SUM(pd.SchoolRemittances), 0) AS SchoolRemittances,
COALESCE(SUM(pd.SchoolRemittancesPending), 0) AS SchoolRemittancesPending,
a.SchoolYearId,
COALESCE(SUM(pd.SchoolPayments + pd.SchoolRemittances), 0) AS TotalReceipts
FROM
Billing_AccountCharge ac WITH(NOLOCK)
INNER JOIN Billing_AccountInvoice ai WITH(NOLOCK) ON ac.AccountInvoiceId = ai.AccountInvoiceId
INNER JOIN Billing_Account a WITH(NOLOCK) ON ai.AccountId = a.AccountId
INNER JOIN Billing_PaymentMethod pm WITH(NOLOCK) ON pm.PaymentMethodId = CASE
WHEN ai.AutomaticPaymentEligible = 1 THEN a.PaymentMethodId
ELSE 3
END
INNER JOIN Billing_AccountPaymentDate apd WITH(NOLOCK) ON
apd.AccountPaymentMethodId = pm.AnticipatedAccountPaymentMethodId AND
apd.DueDate = ai.DueDate AND
apd.HoldForFee = a.HoldPaymentForFee
INNER JOIN Billing_ChargeItem ci WITH(NOLOCK) ON ac.ChargeItemId = ci.ChargeItemId
LEFT OUTER JOIN PaymentData pd WITH(NOLOCK) ON ac.AccountChargeId = pd.AccountChargeId
WHERE
ai.AccountInvoiceStatusId <> 4 AND
ci.RemitToSchool = 1 AND
a.SchoolId = 6 AND
a.SchoolYearId = 12
GROUP BY
apd.DueDate,
apd.RemittanceEffectiveDate,
a.SchoolId,
a.SchoolYearId
HAVING
SUM(ac.NetAmount) <> 0
ORDER BY
apd.DueDate ASC;

sql case in column and where section without repeating the case

I have a sql statement like this but with a very long case expression in it and I need it in the where as well as in the column. Is there a way to use the case without repeating it in the column and where section.
select * from c.name, (case when c.age = 1 then 0 when c.age = 2 then 1 ... etc else -1 end;)
from customer c
where (case when c.age = 1 then 0 when c.age = 2 then 1 ... etc else -1 end;) > 0
Typically you would use a subquery to get around this problem:
SELECT *
FROM
(
SELECT c.name,
CASE WHEN c.age = 1 THEN 0 WHEN c.age = 2 THEN 1 ELSE -1 END AS val
FROM customer c
INNER JOIN employee e ON c.emp_id = e.id
) t
WHERE val > 0;
But in practice if you had a list of age values which get mapped to positive values, you could just use a single level query with a WHERE clause:
SELECT c.name,
CASE WHEN c.age = 1 THEN 0 WHEN c.age = 2 THEN 1 ELSE -1 END AS val
FROM customer c
WHERE age IN (2, ...);
A simple way of consolidating would be to use a lateral join
select *
from customer c,
lateral (values(case when c.age = 1 then 0 when c.age = 2 then 1 ... etc else -1 end))v(AgeCheck)
where AgeCheck > 0;

what is mean by select * from ... where 1=condition in sql

I have seen in sql procedures: select * from table 1=1
SELECT DISTINCT b.book_number AS book_number,
b.book_title AS b.nook_title,
o.order_summary AS order_summary,
otm.total_amt
FROM books b(nolock)
INNER JOIN books_detail bd (nolock)
ON b.b_id = bd.b_id
INNER JOIN order o(nolock)
ON o.author_id = b.author_id
INNER JOIN order_master otm(nolock)
ON otm.order_number = otm.order_number
WHERE b.status = 'AVAILABLE'
AND ( otm.cnt > 4
OR otm.total > 150
OR 1 = ( CASE
WHEN #order = 'Any' THEN 0
WHEN #order = 'devotional' THEN 1
WHEN #order = 'investigation' THEN 1
ELSE 0
END ) )
my question here is what is the use of
OR 1 = ( CASE
WHEN #order = 'Any' THEN 0
WHEN #order = 'devotional' THEN 1
WHEN #order = 'investigation' THEN 1
ELSE 0
END ) )
If you follow the logical process flow you will see that the result of the case expression is either a 1 or 0 and the where clause is checking to see if 1 is returned.
In this particular instance, the expression is equivalent to:
#order in ('devotional', 'investigation')

Sum values are inflated when I join another table

I have two queries that return the result sets I want, it is one row per user per day. The problem is that when I try to join the two queries, by userid, I get inflated results because the user is in the table multiple times for each day. How do I join them and avoid having the inflated results?
**Query 1**
SELECT AAL.UserID
, SUM(AAL.Dur)/60 AS 'LIM'
, SUM(CASE When AAL.DUR = 'av' then AAL.Dur/60
Else 0 END) AS 'AVAIL'
FROM WG
INNER JOIN AAL
on WG.UserID=AAL.UserID
and WG.SiteID=AAL.SiteID
WHERE WG.WG = 'OP'
AND DATEDIFF(day,AAL.Date,GETDATE()) = 1
GROUP BY AAL.UserID
**Query 2**
SELECT R.UserID
, SUM(CASE When R.StID = 4 then 1
Else 0 End) AS 'Rf Ct'
FROM R
INNER JOIN WG
on R.UserID = WG.UserID
WHERE WG.WG = 'OP'
AND DATEDIFF(day,R.Date,GETDATE()) = 1
GROUP BY R.UserID
**JOIN ATTEMPT**
SELECT AAL.UserID
, SUM(AAL.Dur)/60 AS 'LIM'
, SUM(CASE When AAL.DUR = 'av' then AAL.Dur/60
Else 0 END) AS 'AVAIL'
, SUM(CASE When R.StID = 4 then 1
Else 0 End) AS 'Rf Ct'
FROM WG
INNER JOIN AAL
on WG.UserID=AAL.UserID
and WG.SiteID=AAL.SiteID
INNER JOIN R
on AAL.UserID=R.UserID
WHERE WG.WG = 'OP'
AND DATEDIFF(day,AAL.Date,GETDATE()) = 1
GROUP BY AAL.UserID
You are not using WB in the query. So, just use exists or in:
SELECT R.UserID, SUM(CASE When R.StID = 4 then 1 Else 0 End) AS 'Rf Ct'
FROM R
WHERE DATEDIFF(day, R.Date, GETDATE()) = 1 AND
EXISTS (SELECT 1 FROM WB WHERE R.UserID = WG.UserID AND WG.WG = 'OP')
GROUP BY R.UserID;
You should understand the reason why the number gets multiplied -- multiple rows in WG correspond to a single R.ID.

How can I add a sub-query to this cursor?

I tried to add a sub query (StoCount) to the following cursor:
DECLARE trans_cur CURSOR FOR
SELECT b.TransportNumber,
SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed,
COUNT(*) AS Total,
SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
(SELECT COUNT(*) FROM StorageTransportOrderItem WHERE DeliveryNumber = a.DeliveryNumber AND DeliveryItemNumber = a.DeliveryItemNumber) As StoCount
FROM DeliveryItem a
INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
WHERE a.StorageLocationNumber IS NOT NULL
AND a.Deleted <> 1
AND c.CommissioningArea LIKE #commissioningArea
AND d.TransportStatus < 70
GROUP BY b.TransportNumber
but when I always get the error message:
Msg 8120, Level 16, State 1, Procedure sp_CalculateTransportProgress,
Line 41 Column 'DeliveryItem.DeliveryNumber' is invalid in the select
list because it is not contained in either an aggregate function or
the GROUP BY clause. Msg 8120, Level 16, State 1, Procedure
sp_CalculateTransportProgress, Line 41 Column
'DeliveryItem.DeliveryItemNumber' is invalid in the select list
because it is not contained in either an aggregate function or the
GROUP BY clause.
My goal is to add this single column (StoCount) to the cursor without modifying the query too much.
Is that possible?
You could move the correlated subquery to a cross apply
SELECT b.TransportNumber,
SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed,
COUNT(*) AS Total,
SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
MAX(e.Freq) AS StoCount
FROM DeliveryItem a
INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
CROSS APPLY (
SELECT COUNT(*) freq FROM StorageTransportOrderItem s
WHERE s.DeliveryNumber = a.DeliveryNumber AND s.DeliveryItemNumber = a.DeliveryItemNumber
) e
WHERE a.StorageLocationNumber IS NOT NULL
AND a.Deleted <> 1
AND c.CommissioningArea LIKE #commissioningArea
AND d.TransportStatus < 70
GROUP BY b.TransportNumber
Edit by xsl:
I had to modify the query a bit, so that it returned the correct results for my database:
SELECT b.TransportNumber,
SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed,
COUNT(*) AS Total,
SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
SUM(e.Freq) AS StoCount
FROM DeliveryItem a
INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
CROSS APPLY (
SELECT COUNT(1) freq FROM StorageTransportOrderItem s
WHERE
s.DeliveryNumber = a.DeliveryNumber
AND s.DeliveryItemNumber = a.DeliveryItemNumber
AND s.MaterialNumber = a.MaterialNumber
) e
WHERE a.StorageLocationNumber IS NOT NULL
AND a.Deleted <> 1
AND c.CommissioningArea LIKE #commissioningArea
AND d.TransportStatus < 70
GROUP BY b.TransportNumber