Reputation: 6611
Thanks in Advance, i use an oracle 10g. In SQL case statement we pass the value and check the case according to value and return string. But instead of returning String, i want to return an expression. Is this is possible using oracle SQL query CASE statement for returning an expression? I do the following and oracle generate an error ORA-00905:Missing Keyword
SELECT ECL_CONTROL,
CASE
WHEN ECL_CONTROL = 'N' THEN ('##0') = ('##0')
WHEN ECL_CONTROL = 'Y' THEN (NVL(IL.ECL, 'X') = NVL(IM.ECL, 'X'))
END
FROM ITEM_CONTROL WHERE ITEM_NO = '2N2907A'
But The following run successfully :
SELECT ECL_CONTROL,
CASE
WHEN ECL_CONTROL = 'N' THEN 'test'
WHEN ECL_CONTROL = 'Y' THEN 'demo'
END
FROM ITEM_CONTROL WHERE ITEM_NO = '2N2907A'
I want to use this query as the inner query and return and expression for outer query. My query is following :
SELECT LSM.ACTIVE_FLAG, LSM.ITEM_NO, IL.ECL, LSM.SERIAL_NO, IL.WAREHOUSE, IL.BIN, LSM.TOOL_STATUS_CODE,
LLG.NEXT_CAL_DATE, IM.PRODUCT_GROUP
FROM LS_SERIAL_MASTER LSM, LS_LIFE_LOG LLG, ITEM_LOCATION IL, ITEM_MASTER IM
WHERE IL.PLANT = IM.PLANT AND IL.ITEM_NO = IM.ITEM_NO
AND IM.PLANT = LSM.PLANT AND IM.ITEM_NO = LSM.ITEM_NO AND NVL(IM.PRODUCT_GROUP, 'X') = NVL('PUMP', 'X')
AND LSM.PLANT = LLG.PLANT AND LSM.ITEM_NO = LLG.ITEM_NO AND LSM.SERIAL_NO = LLG.SERIAL_NO
AND LSM.LIFE_TRANS_ID = LLG.TRANS_ID AND LLG.SERIAL_NO = IL.SERIAL_NO
AND (SELECT ECL_CONTROL,
CASE ECL_CONTROL
WHEN ECL_CONTROL = 'N' THEN ('##0' = '##0')
WHEN ECL_CONTROL = 'Y' THEN (NVL(IL.ECL, 'X') = NVL(IM.ECL, 'X'))
END AS ECL_CONTROL_TXT
FROM ITEM_CONTROL WHERE ITEM_NO = '2N2907A')
AND LLG.MAINT_LMT_ID IN('T', 'U')
AND LLG.NEXT_CAL_DATE BETWEEN TO_DATE('02/1/2014', 'MM/DD/YYYY') AND TO_DATE('02/11/2014', 'MM/DD/YYYY').
My actual task is return an expression from inner query and used in outer query.
Upvotes: 1
Views: 2209
Reputation: 191315
No, what you've shown isn't possible. It doesn't make sense to have an expression in the select
really. You can have an expression evaluated instead of using a fixed string:
SELECT ECL_CONTROL,
CASE
WHEN ECL_CONTROL = 'N' THEN '##0'
WHEN ECL_CONTROL = 'Y' THEN NVL(IL.ECL, 'X')
END
FROM ITEM_CONTROL WHERE ITEM_NO = '2N2907A'
But you can't return the actual expression. In the code you've shown the first expression would always evaluate to true
anyway (and booleans don't exist in plain SQL either), so I think this is maybe what you actually intended and you're confused about how to assign the expression value. You haven't shown where IL
and IM
come from so it's hard to tell quite what you want.
You can use a case
directly in a where
clause:
SELECT ...
FROM IM, IL, ITEM_CONTROL -- joined in some way
WHERE CASE
WHEN ECL_CONTROL = 'N' THEN '##0'
WHEN ECL_CONTROL = 'Y' THEN NVL(IL.ECL, 'X')
END = CASE
WHEN ECL_CONTROL = 'N' THEN '##0'
WHEN ECL_CONTROL = 'Y' THEN NVL(IM.ECL, 'X')
END
Though that might be clearer as:
WHERE ECL_CONTROL = 'N' OR NVL(IL.ECL, 'X') = NVL(IM.ECL, 'X')
From the larger query you added:
SELECT LSM.ACTIVE_FLAG, LSM.ITEM_NO, IL.ECL, LSM.SERIAL_NO, IL.WAREHOUSE,
IL.BIN, LSM.TOOL_STATUS_CODE, LLG.NEXT_CAL_DATE, IM.PRODUCT_GROUP
FROM LS_SERIAL_MASTER LSM, LS_LIFE_LOG LLG, ITEM_LOCATION IL, ITEM_MASTER IM
WHERE IL.PLANT = IM.PLANT AND IL.ITEM_NO = IM.ITEM_NO
AND IM.PLANT = LSM.PLANT AND IM.ITEM_NO = LSM.ITEM_NO
AND NVL(IM.PRODUCT_GROUP, 'X') = NVL('PUMP', 'X')
AND LSM.PLANT = LLG.PLANT AND LSM.ITEM_NO = LLG.ITEM_NO
AND LSM.SERIAL_NO = LLG.SERIAL_NO
AND LSM.LIFE_TRANS_ID = LLG.TRANS_ID AND LLG.SERIAL_NO = IL.SERIAL_NO
AND LLG.MAINT_LMT_ID IN('T', 'U')
AND LLG.NEXT_CAL_DATE BETWEEN TO_DATE('02/1/2014', 'MM/DD/YYYY')
AND TO_DATE('02/11/2014', 'MM/DD/YYYY')
AND ((SELECT ECL_CONTROL FROM ITEM_CONTROL WHERE ITEM_NO = '2N2907A') = 'N'
OR NVL(IL.ECL, 'X') = NVL(IM.ECL, 'X'))
... though since the subquery is looking for a single row - with a fixed item_no
that has relation to the other columns with the same name you reference in other tables - you could just include that table in the main query.
Either way. this would be clearer with explicit joins, incidentally; rather outside the scope of the question, but taking on your comment that the item_no
is actually related, something like:
SELECT LSM.ACTIVE_FLAG, LSM.ITEM_NO, IL.ECL, LSM.SERIAL_NO, IL.WAREHOUSE,
IL.BIN, LSM.TOOL_STATUS_CODE, LLG.NEXT_CAL_DATE, IM.PRODUCT_GROUP
FROM LS_LIFE_LOG LLG
JOIN LS_SERIAL_MASTER LSM ON LSM.PLANT = LLG.PLANT
AND LSM.ITEM_NO = LLG.ITEM_NO
AND LSM.SERIAL_NO = LLG.SERIAL_NO
AND LSM.LIFE_TRANS_ID = LLG.TRANS_ID
JOIN ITEM_CONTROL IC ON IC.ITEM_NO = LSM.ITEM_NO
JOIN ITEM_MASTER IM ON IM.PLANT = LSM.PLANT
AND IM.ITEM_NO = IC.ITEM_NO
JOIN ITEM_LOCATION IL ON IL.PLANT = IM.PLANT
AND IL.ITEM_NO = IM.ITEM_NO
AND IL.SERIAL_NO = LLG.SERIAL_NO
AND (IC.ECL_CONTROL = 'N' OR NVL(IL.ECL, 'X') = NVL(IM.ECL, 'X'))
WHERE LLG.MAINT_LMT_ID IN ('T', 'U')
AND LLG.NEXT_CAL_DATE BETWEEN TO_DATE('02/1/2014', 'MM/DD/YYYY')
AND TO_DATE('02/11/2014', 'MM/DD/YYYY')
AND NVL(IM.PRODUCT_GROUP, 'X') = NVL('PUMP', 'X')
NVL('PUMP', 'X')
doesn't make sense though - the NVL()
is pointless around a fixed value. Maybe instead of AND NVL(IM.PRODUCT_GROUP, 'X') = NVL('PUMP', 'X')
you mean AND (IM.PRODUCT_GROUP IS NULL OR IM.PRODUCT_GROUP = 'PUMP')
?
Upvotes: 1