Rewrite subquery with calculation in SQL to CASE statement - sql

I have, as a part of a bigger query, some subqueries that I would like to convert to CASE statements instead.
The subquery looks like this (and works):
(SELECT (((SUM(DAm)-(SUM(StcCst)*-1))*100)/NULLIF(SUM(DAm),0)) AS 'DG' FROM [F0001].[dbo].[ProdTr] WHERE AcYrPr = '201601' AND ProdTr.TrTp = 1 AND [F0001].[dbo].[ProdTr].CustNo = '12773') AS dg_period_1
However, I don't seem to find any logical way to put this into a CASE-statement.
Any help would be appreciated!

(
SELECT CASE
WHEN SUM(t1.DAm) <> 0
THEN (SUM(t1.DAm) + SUM(t1.StcCst)) * 100 / SUM(t1.DAm)
ELSE 0 /* or whatever you want to have in this case */
END AS 'DG'
FROM [F0001].[dbo].[ProdTr] t1
WHERE t1.AcYrPr = '201601' AND
t1.TrTp = 1 AND
t1.CustNo = '12773'
) AS dg_period_1
I also removed some unneeded parentheses and simplified an operation (x - (y * -1) = x + y)

You could use the following statement with CASE provided you want to return a null when SUM(DAm) is null or 0.
(SELECT CASE
WHEN SUM(DAm) IS NOT NULL and SUM(DAm) <> 0 THEN (((SUM(DAm) - (SUM(StcCst) * -1)) * 100) /SUM(DAm))
ELSE NULL
END AS 'DG'
FROM [F0001].[dbo].[ProdTr]
WHERE AcYrPr = '201601'
AND ProdTr.TrTp = 1
AND [F0001].[dbo].[ProdTr].CustNo = '12773') AS dg_period_1

Related

T - SQL variable programming like in R/C++

I have sql data of 2,907,735 rows and 32 columns.. and I want to perform simple mathematical calculations for each row using the attributes in that row.
Currently, I had to program this in R which is taking so much time, and I'm not sure SQL has the capability to do this simple programming calculations are not.
If it has the capability, I think SQL will be faster.
Please help.
q1=0
q2=0
q3=0
q4=0
frac2final=0
sumcnt = 0
cumcnt = 0
year = 0
startpoint1 = 0
startpoint2 = 0
sumexpect = 0
cntatmind = 0
cntatmaxd = 0
exatmind = 0
exatmaxd = 0
ex1=0
ex2=0
ex3=0
ex4=0
cumcntfirst = 0
for (i in 1:2907735)
{
frac2final = a[i,25]
sumcnt = a[i,31]
cumcnt = frac2final + sumcnt
year = a[i,12]
sumexpect = a[i,32]
cntatmind = a[i,4]
cntatmaxd = a[i,5]
exatmind = a[i,6]
exatmaxd = a[i,7]
if(year !=2016) {
startpoint1 = 0
startpoint2=0}
else
{startpoint1 = frac2final
startpoint2 = frac2final}
#cumcntfirst = startpoint2 + cntatmind
if (startpoint1<=0.25) q1 = max( (min(0.25,cumcnt) - startpoint1),0) else q1=0
startpoint1 = startpoint1 + q1
if(startpoint1<=0.5) q2 = max( (min(0.5,cumcnt) - startpoint1),0) else q2=0
startpoint1 = startpoint1 + q2
if(startpoint1<=0.75) q3 = max( (min(0.75,cumcnt) - startpoint1),0) else q3=0
startpoint1 = startpoint1 + q3
q4 = max(0,sumcnt-q1-q2-q3)
a[i,33] = q1
a[i,34] = q2
a[i,35] = q3
a[i,36] = q4
}
Remember in SQL we work with sets, not loops. An "Intermediate result" would be an in intermediate result set, which is synonymous with a subquery (for the most part).
As an example using your R as a starting point:
SELECT q1,
startpoint1 + q1 AS startpoint1
FROM (
startpoint1,
SELECT CASE
WHEN startpoint1 <= 0.25
THEN CASE
WHEN 0 > CASE
WHEN 0.25 > cumcnt
THEN 0.25
ELSE cumcnt
END - startpoint1
THEN 0
ELSE CASE
WHEN 0.25 > cumcnt
THEN 0.25
ELSE cumcnt
END - startpoint1
END
ELSE 0
END AS q1
FROM (
SELECT CASE
WHEN year <> 2016
THEN 0
ELSE frac2final
END AS startpoint1,
CASE
WHEN year <> 2016
THEN 0
ELSE frac2final
END AS startpoint2
FROM yourTable
) subquery1
) subquery2
There is no function to replicate your min and max here so we have to use CASE statements to do the logic. There are many examples of UDFs out there to give this functionality though. The trick is that min and max DO exist in tsql, but it takes the min/max of values in a column when aggregating many records together. Your use here is synonymous with UDFs generally called GREATEST() and LEAST() to compare two or more fields from the same record.
To get a grasp on how this is working, run the inner-most subquery and see what it produces, then run the next subquery (which has subquery1 inside of it) to see how it uses those results... then you can just reuse this logic to build your remaining fields for your final result set.

Is there a way to ignore the AND in a CASE when something is true?

I have this Where clause
Select * From Student_Info si
Inner Join Certifications cc
Inner Join Cert_Earned ce
Where si.grad_date = #grad_date
AND cc.org_no = #org_no
but I need an additional AND that should be ignored if it turns out the value is false, I will want ALL certificates
AND cc.industrial = CASE WHEN #industrial = 0 THEN Do Nothing
Else #industrial
This would normally be expressed as:
AND (#industrial = 0 OR ccc.industrial = #industrial)
It sounds like you just want to add a predicate that does an OR between two different conditions
AND (#industrial = 0 or ccc.industrial = #industrial)
You can do something like this with CASE functions:
AND 1 = (CASE WHEN #industrial = 0 THEN 1
ELSE CASE WHEN cc.industrial = #industrial THEN 1 END
END)
or if cc.industrial is not nullable, then maybe:
AND cc.industrial = CASE WHEN #industrial = 0 THEN cc.industrial
Else #industrial END

Combining Case Statements in a View

I have these two case statements and can not for the life of me figure out how to combine them to show in a MSSQL view. Any help would be great.
CASE WHEN [ordertype] = '2' THEN [CommissionAmt1] * - 1 ELSE [CommissionAmt1] END
and
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN 0 ELSE CommissionAmt1 END
Just adding the first case to wherever the CommissionAmt1 is referenced in the second statement.
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN
0
ELSE
CASE WHEN [ordertype] = '2' THEN
[CommissionAmt1] * - 1
ELSE
[CommissionAmt1]
END
END
Or going the other way. It was hard to understand which way the calculation needs to be performed. The only hint was []
CASE WHEN [ordertype] = '2' THEN
(
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN
0
ELSE
CommissionAmt1
END
) * - 1
ELSE
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN
0
ELSE
CommissionAmt1
END
END
Either way, you would be able to save some calculations by sub querying the dependent value.
SELECT
*,
ValueWithDependant=CASE WHEN (Dependant>0) THEN (SomeValue / Dependant) ELSE NULL END
FROM
(
SELECT
X,Y,Z,
Dependant=CASE WHEN SomeValue=1 THEN 1 ELSE 0 END
FROM
SomeTable
)AS DETAIL

SQL Server : IF Condition in WHERE clause

I have a bit parameter
#IsInRetry
If it is false I have to set the where condition to
attempts = 0
else if it is true I have to set the where condition to
attempts > 0
How could this be done?
Try this way:
( (#IsInRetry = 0 and attempts = 0) or (#IsInRetry = 1 and attempts > 0) )
Try this:
WHERE (attempts = #IsInRetry or (#IsInRetry = 1 and attempts > 0))
Try this, should work also for negative attempts :-)
#IsInRetry = (attempts > 0)
Greetings.
This:
if #IsInRetry = 0x0
BEGIN
SELECT * FROM dbo.tbl
WHERE attempts = 0
END
ELSE
BEGIN
SELECT * FROM dbo.tbl
WHERE attempts = 1
END

Conditional operator in Transact-sql

Is there a way to do this shorter, for instance using some sort of conditional operator in Transact-sql?
IF #ParentBinaryAssetStructureId = -1
BEGIN
SET #ParentBinaryAssetStructureId = NULL
END
UPDATE BinaryAssets.BinaryAssetStructures
SET ParentBinaryAssetStructureId = #ParentBinaryAssetStructureId
WHERE BinaryAssetStructureId = #OriginalBinaryAssetStructureId
USE NULLIF()
UPDATE BinaryAssets.BinaryAssetStructures
SET ParentBinaryAssetStructureId = NULLIF(#ParentBinaryAssetStructureId,-1)
WHERE BinaryAssetStructureId = #OriginalBinaryAssetStructureId
The ternary (conditional) operator in c like languages:
x = doSomething ? 5 : 7
would be written like this in SQL:
SELECT #x = CASE WHEN #doSomething = 1 THEN 5 ELSE 0 END
There can be multiple cases (when clauses):
SELECT #x = CASE WHEN #doSomething = 1 THEN 5 WHEN #somethingElse = 1 THEN 20 ELSE 0 END
UPDATE BinaryAssets.BinaryAssetStructures
SET ParentBinaryAssetStructureId =
CASE ParentBinaryAssetStructureId
WHEN -1 THEN NULL
ELSE ParentBinaryAssetStructureId
END
WHERE BinaryAssetStructureId = #OriginalBinaryAssetStructureId
Give that a whirl