Need to verify I am understanding SQL Logic - sql-server

I would like to know if I have this SQL logic decoded correctly. Here is the the SQL:
,[hrs].[Hours] - SUM(CASE WHEN [UnitState].[UnitStateType] <> 'ACTIVE' THEN [Allocation].[AllocatedEnergyMwh] ELSE 0 END / CAST([Unit].[NetDependableCapacity] AS FLOAT)) AS SH
I interpret this as saying:
if [UnitState].[UnitStateType] does not equal active then SH equals the sum of [Allocation].[AllocatedEnergyMwh] /
(float)[Unit].[NetDependableCapacity].
else SH = [hrs].[Hours]

Not exactly.
There is no else for SH. The else only affects the sum aggregate. More accurately, it says:
SH = hours -
(the sum of AllocatedEnergyMwh where StateType != ACTIVE) / NetDependableCapacity
The else is only used to ignore the active AllocatedEnergyMwh in the sum. It does this by setting AllocatedEnergyMwh = 0 in those cases.

It's close but you missed the [hrs].[Hours] - case part for the first one.
if [UnitState].[UnitStateType] does not equal active
then SH equals [hrs].[Hours] minus the sum of [Allocation].[AllocatedEnergyMwh] / (float)[Unit].[NetDependableCapacity].
else SH = [hrs].[Hours] minus (0)/[Unit].[NetDependableCapacity]

if [UnitState].[UnitStateType] does not equal active then
[hrs].[Hours] minus sum([Allocation].[AllocatedEnergyMwh] / [Unit].[NetDependableCapacity])
otherwise
[hrs].[Hours] minus sum(0/[Unit].[NetDependableCapacity]) -->meaning [hrs].[Hours] - 0

Related

How can I make the following variable on SPSS?

I have a variable with values from -100 to 100.
I want a new variable where -14 to 14 will be 1 and all others will be 0.
I have this so far but I get an error.
DO IF (Rad_Start_Minus_Chemo_start GT -14).
Compute NACRT =1.
ELSE IF (Rad_Start_Minus_Chemo_start LT 14).
COMPUTE NACRT=1
ELSE IF (Rad_Start_Minus_Chemo_start GT 14).
Compute NACRT=0.
ELSE IF (Rad_Start_Minus_Chemo_start LT -14).
Compute NACRT=0.
END IF.
You may use RECODE:
RECODE Rad_Start_Minus_Chemo_start (-14 THRU 14 = 1) (ELSE = 0) /INTO NACRT.
or
COMPUTE NACRT = RANGE(Rad_Start_Minus_Chemo_start, -14,14).
(this will compute NACRT as a boolean 0/1 variabile; less flexible than recode, but in your case it gets the job done).

Store Operators like >= OR <= in Microsoft Access

I have certain values that are needed for validation in Forms, either they look like Value X >= 0 but it could also be X <= 0, it depends on what operator should be used. How can I store such a value?
(I use MS SQL Server + Access as Frontend)
I basicly wanna store the Value and if it needs to be bigger than or smaller than.
Store the value, as usual, in a field, and the operator in another field as Short Text.
The you can use Eval:
Result = Eval("" & [ValueField] & [OperatorField] & "0")
You can store your value as it is, and to check if this value is positive or not you have two ways
First one
Create a computed column to check the Value column as
CREATE TABLE YourTable(
YourValue INT,
IsPositive AS CASE WHEN YourValue < 0 THEN 0 ELSE 1 END
);
INSERT INTO YourTable (YourValue) VALUES
(1), (-1);
SELECT *
FROM YourTable;
Second one
Use a CASE expression (or even you can create a view) as
SELECT CASE WHEN YourValue < 0 THEN 0 ELSE 1 END IsPositive,
--...
FROM YourTable;

want to convert negative number to positive

I have a below query which I have used this in a procedure and want to convert one number into positive as right now it is negative.
UPDATE SHIPMENT
SET TOTAL_SHIP_UNIT_COUNT = (
CASE
WHEN V_SHIP_UNIT_COUNT > v_diff_cost
THEN V_SHIP_UNIT_COUNT - v_diff_cost
ELSE v_diff_cost - V_SHIP_UNIT_COUNT
END)
WHERE SHIPMENT_GID = v_shipment_id;
COMMIT;
in this query v_diff_cost value is negative so while performing ( V_SHIP_UNIT_COUNT - v_diff_cost) action it is adding both the values so if I will convert v_diff_cost value to positive then while subtracting it will give me the right result.
Suppose V_SHIP_UNIT_COUNT value is 33 and v_diff_cost value is -10 then in this case it should perform the action as 33-10 = 23 but it is doing as 33-(-10)= 43 and this should not happen.
kindly help me out.
Thanks
Use ABS() function,
MSDN : A mathematical function that returns the absolute (positive) value of the specified numeric expression.
UPDATE SHIPMENT
SET TOTAL_SHIP_UNIT_COUNT = (
CASE
WHEN V_SHIP_UNIT_COUNT > v_diff_cost
THEN V_SHIP_UNIT_COUNT - ABS(v_diff_cost)
ELSE ABS(v_diff_cost) - V_SHIP_UNIT_COUNT
END)
WHERE SHIPMENT_GID = v_shipment_id;
COMMIT;
Try this code:
UPDATE SHIPMENT
SET TOTAL_SHIP_UNIT_COUNT = (
CASE
WHEN V_SHIP_UNIT_COUNT > v_diff_cost
THEN V_SHIP_UNIT_COUNT - abs(v_diff_cost)
ELSE v_diff_cost - abs(V_SHIP_UNIT_COUNT)
END)
WHERE SHIPMENT_GID = v_shipment_id;
COMMIT;
Try this:
UPDATE SHIPMENT
SET TOTAL_SHIP_UNIT_COUNT = ABS(V_SHIP_UNIT_COUNT - ABS(v_diff_cost))
WHERE SHIPMENT_GID = v_shipment_id;

How to protect sql statement from Divide By Zero error

I'm in the process of creating some reports that take a finite total (lets say 2,500) of products (for this example lets say Ice Cream Cones) and counts how many of them were broken before serving.
Now the actual count code of broken cones I've got down.
SELECT COUNT(broken_cones) FROM [ice].[ice_cream_inventory]
WHERE broken_cones = 'Yes'
However, I need a percentage of broken cones from this total as well. I've been playing around with the code but I keep running into a 'Divide By Zero' error with this code below.
SELECT CAST(NULLIF((.01 * 2500)/Count(broken_cones), 0) AS
decimal(7,4)) FROM [ice].[ice_cream_inventory] WHERE broken_cones = 'Yes'
For right now, there aren't any broken cones (and won't be for a while) so the total right now is zero. How can I show the NULL scenario as zero?
I tried to place an ISNULL statement in the mix but I kept getting the 'Divide by Zero' error. Am I even doing this right?
::edit::
Here's what I ended up with.
SELECT
CASE
WHEN COUNT(broken_cones) = 0 then 0
ELSE CAST(NULLIF((.01 * 2500)/Count(broken_cones), 0) AS decimal(7,4))
END
FROM [ice].[ice_cream_inventory] WHERE broken_cones = 'Yes'
Use a case statement.
SELECT
CASE WHEN COUNT(broken_cones) = 0 then 0
ELSE CAST(NULLIF((.01 * 2500)/Count(broken_cones), 0) AS decimal(7,4)) END
FROM [ice].[ice_cream_inventory] WHERE broken_cones = 'Yes'
You already have a solution, but this is why your original solution didn't work.
Your NULLIF needs to be moved in order to be effective. It is doing the division before it gets to the NULLIF call. Dividing by null will return a null value.
SELECT CAST((.01 * 2500)/NULLIF(Count(broken_cones), 0) AS decimal(7,4))
FROM [ice].[ice_cream_inventory]
WHERE broken_cones = 'Yes'`
The NULLIF() function is a great way to prevent divide by zero, since anything divide by NULL returns null. The way to use it is as follows:
<expression> / NULLIF( <expression>, 0 )
Unfortunately you've wrapped your whole divide expression in NULLIF() which is why it isn't working for you. So step one is to get it to return NULL if your COUNT() comes back zero:
SELECT
(0.01 * 2500) / NULLIF( COUNT(broken_cones), 0 )
FROM [ice].[ice_cream_inventory]
WHERE broken_cones = 'Yes'
Now you said you wanted that NULL to come back zero? That is where you use ISNULL():
ISNULL(<expression1>, <expression2>)
If the first expression is NULL then return the second expression, so our SQL now becomes:
SELECT
ISNULL(
(0.01 * 2500) / NULLIF( COUNT(broken_cones), 0 ),
0
)
FROM [ice].[ice_cream_inventory]
WHERE broken_cones = 'Yes'

AND/OR based on variable value in stored procedures

I would like to use AND/OR between the conditions in a stored procedure, and the decision is dependent on the parameter value whether it was 0 (AND) or 1 (OR)
Can anyone help me with this please, i guess this is an easy thing to do but i can't seem to figure it out. Thanks
The easiest way (on first glance) would be to concatenate the query string using dynamic SQL, but dynamic SQL has its issues.
See The Curse and Blessings of Dynamic SQL for an in-depth explanation.
So I would try to avoid dynamic SQL, which is no big deal if your queries are not too complex.
The easiest way is just to fire two different queries depending on the parameter value:
CREATE PROCEDURE spTest
#AndOr bit
AS
BEGIN
if #AndOr = 0 begin
select * from YourTable where foo = 1 and bar = 2
end
else begin
select * from YourTable where foo = 1 or bar = 2
end
END
This is of course an example with a very simple query.
If you have lots of queries, or if your queries are very complex, this might not be the best solution because it forces you to duplicate all queries...but as always, it depends :-)
You can implement your logic on a CASE statement. Something like this:
CREATE PROCEDURE dbo.MySP #OrAnd BIT
AS
BEGIN
SELECT *
FROM MyTable
WHERE CASE WHEN Condition1 AND Condition2 AND #OrAnd = 0 THEN 1
WHEN (Condition1 OR Condition2) AND #OrAnd = 1 THEN 1 ELSE 0 END = 1
END
If you convert the simple conditions' boolean results into numeric ones (0 or 1), you will be able to use your parameter in the following way:
(
(CASE WHEN condition1 THEN 1 ELSE 0 END ^ #AndOr)
&
(CASE WHEN condition2 THEN 1 ELSE 0 END ^ #AndOr)
) ^ #AndOr = 1
Here #AndOr is your parameter, ^ is the Transact-SQL bitwise exclusive OR operator, & stands for the bitwise AND in Transact-SQL, and the CASE expressions are used to convert the boolean results into 0 or 1.
If #AndOr = 0 (which means we want AND between the conditions), the above expression effectively boils down to this:
case1 & case2 = 1
because X XOR 0 yields X and so neither individual values of case1 and case2 nor the entire result of the & operator are not affected by the ^ operators. So, when #AndOr is 0, the result of the original expression would be equivalent to the result of condition1 AND condition2.
Now, if #AndOr = 1 (i.e. OR), then every ^ operator in the expression returns the inverted value of its left operand, in other words, negates the left operand, since 1 XOR 1 = 0 and 0 XOR 1 = 1. Therefore, the original expression would essentially be equivalent to the following:
¬ (¬ case1 & ¬ case2) = 1
where ¬ means negation. Or, converting it back to the booleans, it would be this:
NOT (NOT condition1 AND NOT condition2)
According to one of De Morgan's laws,
(NOT A) AND (NOT B) = NOT (A OR B)
Applying it to the above condition, we get:
NOT (NOT condition1 AND NOT condition2) = NOT (NOT (condition1 OR condition2)) =
= condition1 OR condition2
So, when #AndOr is 1, the expression given in the beginning of my answer is equivalent to condition1 OR condition2. Thus, it works like expected based on the value of #AndOr.
Having the input parameter you can use a IF clause to make different selects.
If input parameter = 0 make the AND conditions, otherwise make the OR conditions.
I can't see any particular elegant way to do it. So here's the straightforward approach
create function myfun (#parm1 int, #parm2 int, #andor int) returns int
begin
if (#andor = 0 AND #parm1 = 99 AND #parm2 = 99) return 1
else if (#andor = 1 AND (#parm1 = 99 OR #parm2 = 99)) return 1
return 0
end
go
select dbo.myfun(99,98,0) -- AND condition should return 0
select dbo.myfun(99,98,1) -- OR condition should return 1
select dbo.myfun(98,98,0) -- AND condition should return 0
select dbo.myfun(98,98,1) -- OR condition shoujld return 0

Resources