Consider the following tables
ID_TYPE
ID | TYPE |
---|---|
1 | 3 |
2 | 3 |
3 | 1 |
4 | 2 |
5 | 2 |
ID_HISTORY
DEBIT_ID | DEBIT_LOCATION | AMOUNT | CREDIT_ID | CREDIT_LOCATION | MONTH |
---|---|---|---|---|---|
3 | LOC1 | 100 | 1 | LOC5 | MAY |
4 | LOC2 | 200 | 3 | LOC6 | MAY |
2 | LOC3 | 300 | 5 | LOC7 | MAY |
1 | LOC4 | 400 | 3 | LOC8 | JUNE |
3 | LOC9 | 500 | 2 | LOC10 | JUNE |
Now suppose I want to fetch all rows from ID_HISTORY in the MONTH of MAY, and result should contain only these columns:
Id, Location, Amount
Cases:
DEBIT_ID
is of TYPE
= 3 in the ID_TYPE
table, then pick DEBIT_ID
as "Id", else pick CREDIT_ID
as "Id"DEBIT_ID
is of TYPE
3 in the ID_TYPE
table, then pick DEBIT_LOCATION
as "Location", else pick CREDIT_LOCATION
as "Location"For example, above tables should result in the following:
Id | Location | Amount |
---|---|---|
1 | LOC5 | 100 |
2 | LOC3 | 300 |
I know that something like the following should work:
SELECT
(CASE
WHEN (Tab.DEBIT_ID IN (
SELECT ID
FROM ID_TYPE Typ
WHERE Typ.TYPE = 3)
) THEN Tab.DEBIT_ID
ELSE Tab.CREDIT_ID END
) "Id",
(CASE
WHEN (Tab.DEBIT_ID IN (
SELECT ID
FROM ID_TYPE Typ
WHERE Typ.TYPE = 3)
) THEN Tab.DEBIT_LOCATION
ELSE Tab.CREDIT_LOCATION END
) "Location",
Tab.AMOUNT "Amount"
FROM (
SELECT *
FROM ID_HISTORY Tab
WHERE Tab.MONTH = 'MAY'
--this block will be very complicated and contain complex multi-level queries to fetch data
)
But as you can see this will be inefficient as I have to basically duplicate the full case logic for each conditional columns. Also, this is no way "clean" in case there are a lot of similar columns.
Also, if the case logic is complex, it will be inefficient even further. It would be better if i could select multiple columns in THEN
/ ELSE
cases. I tried doing that, but it just gives me "ORA-00913: too many values" error.
What would be the optimized version?
You could use a join to remove the sub-queries:
SELECT CASE
WHEN typ.id IS NOT NULL
THEN h.debit_id
ELSE h.credit_id
END AS id,
CASE
WHEN typ.id IS NOT NULL
THEN h.debit_location
ELSE h.credit_location
END AS location,
h.AMOUNT
FROM (
SELECT *
FROM ID_HISTORY
WHERE MONTH = 'MAY'
-- this block will be very complicated and contain complex multi-level queries to fetch data
) h
LEFT OUTER JOIN (
SELECT id
FROM id_type
WHERE type = 3
) typ
ON (h.debit_id = typ.id)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.