ISNULL, SQL, Using a select statement as the second parameter - sql

I don't know if this is possible in SQL or if I have to write a stored procedure but I'm trying to use the ISNULL function as below so that when the parameter #sku is null I'm using a select statement to bring back all the sku's in the table:
SELECT GooglePrice.idGooglePrice, GooglePrice.idProduct, products.sku, products.wholeprice, products.price as CurrentHMMPrice, GooglePrice.bestPrice, GooglePrice.link, GooglePrice.title, GooglePrice.description, GooglePrice.ourPrice as PriceCompHMMPrice,
GooglePrice.searchType, GooglePrice.shippingCost, GooglePrice.cheapestOrder, GooglePrice.timeStamp,
'ShippingCostNew' = CASE
WHEN GooglePrice.shippingCost = -1 THEN 'N/A'
WHEN GooglePrice.shippingCost = 0 THEN 'Free Shipping'
WHEN GooglePrice.shippingCost > 0 Then cast(GooglePrice.shippingCost as varchar)
END
FROM GooglePrice INNER JOIN
products ON GooglePrice.idProduct = products.idProduct
WHERE (products.supplierCode in (#SupplierCode)) AND ISNULL((products.sku like '%'+#sku+'%'), (products.sku in (select sku from products where products.sku)))
ORDER BY GooglePrice.idGooglePrice

Would be easier with an OR
WHERE
(products.supplierCode in (#SupplierCode))
AND
(products.sku like '%'+#SupplierCode+'%' OR #SupplierCode IS NULL)
This was your intention, no?
AND
products.sku like ISNULL('%'+#SupplierCode+'%',products.sku)
Notes:
leading wildcards can not be optimised and won't use indexes.
I assume you don't have a CSV in #SupplierCode for this products.supplierCode in (#SupplierCode)

Don't overcomplicate it.
Make your WHERE clause:
WHERE
((products.supplierCode in (#SupplierCode)
AND
(products.sku like '%'+#SupplierCode+'%'))
OR (#suppliercode IS NULL)
You don't really explain your logic so I'm guessing, but the idea is to put a separate check for the NULL comparison.

SELECT GooglePrice.idGooglePrice, GooglePrice.idProduct, products.sku, products.wholeprice, products.price as CurrentHMMPrice, GooglePrice.bestPrice, GooglePrice.link, GooglePrice.title, GooglePrice.description, GooglePrice.ourPrice as PriceCompHMMPrice, GooglePrice.searchType, GooglePrice.shippingCost, GooglePrice.cheapestOrder, GooglePrice.timeStamp,
'ShippingCostNew' = CASE
WHEN GooglePrice.shippingCost = -1 THEN 'N/A'
WHEN GooglePrice.shippingCost = 0 THEN 'Free Shipping'
WHEN GooglePrice.shippingCost > 0 Then cast(GooglePrice.shippingCost as varchar)
END
FROM GooglePrice INNER JOIN
products ON GooglePrice.idProduct = products.idProduct
WHERE (products.supplierCode in (#SupplierCode)) AND (#SupplierCode is null or products.sku like '%'+#SupplierCode+'%')
ORDER BY GooglePrice.idGooglePrice

Related

Nested case conditionals in PostgreSQL, syntax error?

I use PostgreSQL and I would like to combine these two case conditions, but when I uncomment the code, I get a syntax error. This is not a difficult instruction. I want to divide or multiply the obtained number depending on the condition. How can I enter it so that the code is compiled?
SELECT
SUM(
CASE
WHEN transactions.recipient_account_bill_id = recipientBill.id AND recipientBill.user_id = 2
THEN 1
ELSE -1
END * transactions.amount_money
/* CASE
WHEN senderBillCurrency.id = recipientBillCurrency.id
THEN NULL
ELSE
CASE
WHEN recipientBillCurrency.base = true
THEN /
ELSE *
END senderBillCurrency.current_exchange_rate
END */
) as TOTAL
FROM transactions
LEFT JOIN bills AS senderBill ON senderBill.id = transactions.sender_account_bill_id
LEFT JOIN bills AS recipientBill ON recipientBill.id = transactions.recipient_account_bill_id
LEFT JOIN currency as senderBillCurrency ON senderBillCurrency.id = senderBill.currency_id
LEFT JOIN currency as recipientBillCurrency ON recipientBillCurrency.id = recipientBill.currency_id
WHERE 2 IN (senderBill.id, recipientBill.id)
You cannot create dynamic SQL expressions like that. A CASE expression cannot return an operator as if SQL was some sort of macro language. You can only return an expression.
You already used the following approach using 1 and -1 with your multiplication. Why not also use it with N and 1/N:
<some expression> * CASE WHEN condition THEN 1 / N ELSE N END
Or in your case:
<some expression> * CASE
WHEN senderBillCurrency.id = recipientBillCurrency.id THEN 1
WHEN recipientBillCurrency.base THEN 1 / senderBillCurrency.current_exchange_rate
ELSE senderBillCurrency.current_exchange_rate
END
Notice, you can put several WHEN clauses in a CASE expression. No need to nest them

CASE with IN clause

I have a condition (in Business objects ) as below
=If([Actual ]=0;Sum([Applied] In ([Project];[ Name];[Number];[Sub ])))
which I need to convert it to CASE statement for my OBIEE
Below is the query I had tried but it doesn't work:
SELECT
CASE
WHEN F.ACTUAL_EQP_COST = 0
THEN SUM((F.HRS_APPLIED) IN(F.PROJECT,F.NAME,F.NUMBER,F.SUB))
ELSE 0
END
FROM F
Probably
select SUM(F.HRS_APPLIED)
from DTS_OSC_WIP_REP_CST_ANALYSIS_A F
where F.ACTUAL_EQP_COST = 0
group by F.PROJECT,F.WIP_ENTITY_NAME,F.OPERATION_NUMBER,F.OPERATION_SUB_SEQ
You can't use "in" inside a "then" statement.
I couldn't understand exactly but something in this direction might help:
select
CASE WHEN F.ACTUAL_EQP_COST = 0
THEN (SELECT SUM(F1.HRS_APPLIED)
FROM DTS_OSC_WIP_REP_CST_ANALYSIS_A F1
WHERE F1.column_name IN (F.PROJECT,F.WIP_ENTITY_NAME,F.OPERATION_NUMBER,F.OPERATION_SUB_SEQ))
ELSE 0 END
from DTS_OSC_WIP_REP_CST_ANALYSIS_A F

SQL Server Multiple Assignments within IF or CASE WHEN block

I was wondering if it's possible to assign values to multiple fields within a block of an IF or CASE WHEN statement in SQL Server 2008? In a project I am working on, when a condition is met, I want to assign specific values to 4 different fields, if not met I want to assign other values to the sames fields.
See examples below.
Thanks in advance for your help. Any tip will be welcome.
SELECT With CASE WHEN
SELECT with IF
SELECT Field1
,Field2
,Field3
CASE
WHEN Condtion1_Met THEN
,Field4 = Value4A
,Field5 = Value5A
,Field6 = Value6A
,Field7 = Value7A
ELSE
,Field4 = Value4B
,Field5 = Value5B
,Field6 = Value6B
,Field7 = Value7B
END
FROM Table1
______________________________________________
SELECT Field1
,Field2
,Field3
IF Condtion1_Met
BEGIN
,Field4 = Value4A
,Field5 = Value5A
,Field6 = Value6A
,Field7 = Value7A
END
ELSE
BEGIN
,Field4 = Value4B
,Field5 = Value5B
,Field6 = Value6B
,Field7 = Value7B
END
FROM Table1
No, this is not possible. A CASE expression (it is considered to be an expression, not a statement) can only return a single value. It can't set multiple values.
And an IF statement can't be used inside a query at all. Instead you could do this:
IF Condition1_Met
SELECT ...
ELSE
SELECT ...
I finally decided to use a WHILE loop combined with IF/ELSE statements to UPDATE the fields in the table.

MSSQL 2008: Problems with the 'Case' - statement

I'm having some troubles finding a solution to my SQL-Problem. I've tried google but so far my search didn't give me any statisfactory results.
I have an SSRS report with two parameters:
#SupplierId NVARCHAR (May contain NULL)
#EmployeeId NVARCHAR (May contain NULL)
My original query retrieved all the employees who came in service during the last year:
SELECT Name, Surname from dbo.Employee Where Employee.DateInService > DATEADD(year,-1,GETDATE())
Right now i want to add those parameters to the query using the following logic.
Remark this is pseudo SQL:
SELECT
...
FROM ...
WHERE Employee.DateInService > DATEADD(year,-1,GETDATE()) AND
IF (LEN(RTRIM(#SupplierId)) = 0 Or #SupplierID IS NULL ) THEN
dbo.Employee.EmployeeId = #EmployeeId
Else
dbo.Employee.SupplierId = #SupplierId
My search sofar led me to the Case statement. I made a query which contains an syntax error (obviously). My base query:
SELECT
...
FROM ...
WHERE Employee.DateInService > DATEADD(year,-1,GETDATE()) AND
CASE WHEN (LEN(RTRIM(#SupplierId)) = 0) THEN
dbo.Employee.EmployeeId = #EmployeeId
Else
dbo.Employee.SupplierId = #SupplierId
Error: Syntax error near '='.
Question 1: Why does he give an error near the '='?
Question 2: How do i correctly implement the following:
CASE WHEN (LEN(RTRIM(#SupplierId)) = 0 "Or #SupplierId is null" ) THEN
Instead of
CASE WHEN (LEN(RTRIM(#SupplierId)) = 0) Then dbo.Employee.EmployeeId = #EmployeeId
WHEN (#SupplierId IS NULL) Then dbo.Employee.EmployeeId = #EmployeeId
ELSE dbo.Employee.EmployeeId = #EmployeeId END
Note: if i've missed a post during my google searches, please don't hesitate to point it out.
Thanks for your help
You can't change the actual query predicate like that with CASE - there are 2 distinct queries depending on the value of #SupplierId. You can conditionally apply the filter as follows (I've assumed the #SupplierId = null flow is the same as the whitespace branch:
SELECT
...
FROM ...
WHERE Employee.DateInService > DATEADD(year,-1,GETDATE())
AND
(
(dbo.Employee.EmployeeId = #EmployeeId
AND (LEN(RTRIM(#SupplierId)) = 0 OR #SupplierId IS NULL))
OR
(dbo.Employee.SupplierId = #SupplierId AND LEN(RTRIM(#SupplierId)) > 0)
)
Although this can be prone to query plan sniffing related performance issues, in which case you might need to consider an alternative approach, e.g. using parameterized dynamic sql to build up and execute the sql, as there are 2 distinct process flows through the query.
Edit
As per Ypercube's comment above, in order to provide the boolean result needed for the predicate, if you can find a hack workaround is to find a way to project a COMMON scalar from each of the CASE .. WHEN row and then do a comparison of the scalar. In the example below, projecting a yes / no flag.
SELECT * FROM dbo.Employee
WHERE
CASE
WHEN (LEN(RTRIM(#SupplierId)) = 0 OR #SupplierId IS NULL)
THEN CASE WHEN dbo.Employee.EmployeeId = #EmployeeId THEN 1 ELSE 0 END
ELSE CASE WHEN dbo.Employee.SupplierId = #SupplierId THEN 1 ELSE 0 END
END = 1;
But the big problem with this approach is performance - the above will require a full scan to determine the results.

Conditional WHERE clause with CASE statement in Oracle

I'm brand-new to the Oracle world so this could be a softball. In working with an SSRS report, I'm passing in a string of states to a view. The twist is that the users could also pick a selection from the state list called "[ No Selection ]" ... (that part was not by doing and I'm stuck with implementing things this way)
If they choose the No Selection option, then I just want to return all states by default, otherwise return just the list of states that are in my comma-separated list.
This really seems like it should be easy but I'm stuck. Here is the code I have so far (just trying to get a sample to work) but my eyes have finally gone crossed trying to get it going.
Could anybody give me some direction on this one please?
begin
:stateCode:='MO,FL,TX';
--:stateCode:='[ No Selection ]';
end;
/
select count(*) as StateCount, :stateCode as SelectedVal
from hcp_state vw
where
(case
when (:stateCode = '') then (1)
when (:stateCode != '') then (vw.state_cd in (:stateCode))
(else 0)
end)
;
You can write the where clause as:
where (case when (:stateCode = '') then (1)
when (:stateCode != '') and (vw.state_cd in (:stateCode)) then 1
else 0)
end = 1;
Alternatively, remove the case entirely:
where (:stateCode = '') or
((:stateCode != '') and vw.state_cd in (:stateCode));
Or, even better:
where (:stateCode = '') or vw.state_cd in (:stateCode)
We can use a CASE statement in WHERE clause as:
SELECT employee_no, name, department_no
FROM emps
WHERE (CASE
WHEN :p_dept_no = 50 THEN 0
WHEN :p_dept_no = 70 THEN 0
ELSE -1
END) = 0;