Nested case conditionals in PostgreSQL, syntax error? - sql

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

Related

ParseException at FROM statement when updating SQL view using AND operator with CASE WHEN

I am getting an error at the FROM sb.v_transactions t line after my CASE WHEN statements. I tried adding commas, parentheses, and am considering perhaps using CTE to create my output. Was wondering if anyone could help me figure out why I'm getting the error? I have a feeling it has something to do with how I'm using the AND operators.
%sql
UPDATE sb.transactions u
SET t.FranchiseStore = u.FranchiseStore
AND t.LocationNumber = u.LocationNumber
AND openflg = CASE openflg
WHEN o.FiscYKey IS NULL THEN 1
ELSE 0
END
AND closeflg_y = CASE closeflg_y
WHEN c.FiscYKey IS NULL THEN 1
ELSE 0
END
AND closeflg_p = CASE closeflg_p
WHEN c.FiscYKey IS NULL THEN 1
ELSE 0
END
AND closeflg_w = CASE closeflg_w
WHEN c.FiscYKey IS NULL THEN 1
t.FiscWkKey THEN 1
ELSE 0
END
-- PARSE EXCEPTION ON THE FROM BELOW. WHY?
FROM sb.v_transactions t
LEFT JOIN sb.v_loc_opendates o
ON t.LocationNumber = o.LocationNumber
LEFT JOIN sb.v_loc_closedates c
ON t.LocationNumber = c.LocationNumber
WHERE t.LocationNumber = u.LocationNumber
AND t.DayDate = u.DayDate

Case expression with Boolean from PostgreSQL to SQL Server

I am translating a query from PostgreSQL to SQL Server. I didn't write the query in PostgreSQL and it's quite complicated for my knowledge so i don't understand every piece of it.
From my understand: we are trying to find the max version from p_policy and when insurancestatus = 7 or 14 / transactiontype = CAN, we compare two dates (whose format are BIG INT).
This is the PG Query:
SELECT *
FROM BLABLABLA
WHERE
pol.vnumber = (
SELECT MAX(pol1.vnumber)
FROM p_policy pol1
AND ( CASE WHEN pol1.insurancestatus IN (7,14)
or pol1.transactiontype IN ('CAN')
-- ('CAN','RCA')
THEN pol1.veffectivedate = pol1.vexpirydate
ELSE pol1.veffectivedate <> pol1.vexpirydate
END
)
AND pol1.vrecordstatus NOT IN (30,254)
etc.
I am used to have a where statement where I compare it to a value. I understand here from the Case statement we will have a boolean, but still that must be compared to something?
Anyway the main purpose is to make it work in SQL, but I believe SQL can't read a CASE statement where THEN is a comparison.
This is what I tried:
SELECT *
FROM BLABLABLA
WHERE pol.vnumber =
(
SELECT MAX(pol1.vnumber)
FROM p_policy pol1
WHERE sbuid = 4019
AND ( CASE WHEN pol1.insurancestatus IN (7,14)
or pol1.transactiontype IN ('CAN')
THEN CASE
WHEN pol1.veffectivedate = pol1.vexpirydate THEN 1
WHEN pol1.veffectivedate <> pol1.vexpirydate THEN 0
END
END
)
AND pol1.vrecordstatus NOT IN (30,254)
etc.
And then I get this error from SQL Server (which directly the last line of the current code - so after the double case statement)
Msg 4145, Level 15, State 1, Line 55
An expression of non-boolean type specified in a context where a condition is expected, near 'AND'.
Thank you !Let me know if it is not clear
I think you want boolean logic. The CASE expression would translate as:
(
(
(pol1.insurancestatus IN (7,14) OR pol1.transactiontype = 'CAN')
AND pol1.veffectivedate = pol1.vexpirydate
) OR (
NOT (pol1.insurancestatus IN (7,14) OR pol1.transactiontype = 'CAN')
AND pol1.veffectivedate <> pol1.vexpirydate
)
)
There are 2 main issues with your snippet, SQL Server-syntax-wise.
SELECT * FROM BLABLABLA WHERE
pol.vnumber = /* PROBLEM 1: we haven't defined pol yet; SQL Server has no idea what pol.vnumber is here, so you're going to get an error when you resolve your boolean issue */
(
SELECT MAX(pol1.vnumber)
FROM p_policy pol1
WHERE sbuid = 4019
AND ( CASE WHEN pol1.insurancestatus IN (7,14)
or pol1.transactiontype IN ('CAN')
THEN CASE
WHEN pol1.veffectivedate = pol1.vexpirydate THEN 1
WHEN pol1.veffectivedate <> pol1.vexpirydate THEN 0
END
END
) /* PROBLEM 2: Your case statement returns a 1 or a 0..
which means your WHERE is saying
WHERE sbuid = 4019
AND (1)
AND pol1.vrecordstatus NOT IN (30,254)
SQL Doesn't like that. I think you meant to add a boolean operation using your 1 or 0 after the parenthesis.
like this: */
= 1
AND pol1.vrecordstatus NOT IN (30,254)

CASE Statement in WHERE statement (equal to and not equal to)

I have the following query where I'm trying to return different values from a table based off the values of a bit variable.
Is there a way I can substitute the where condition to get that to work?
DECLARE #isAggregate bit = 0
SELECT
*
FROM
Fields
WHERE
FieldType
CASE
WHEN #isAggregate = 1 THEN = 'Aggregate'
WHEN #isAggregate = 0 THEN <> 'Aggregate'
END
You can use boolean logic, case expression will not work in this way :
where (#isAggregate = 1 and FieldType = 'Aggregate') or
(#isAggregate = 0 and FieldType <> 'Aggregate')

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

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

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