简体   繁体   中英

Oracle: DECODE and WHERE Clause

So I've been trying to deal with a poorly optimized/created database. I know you can use decode within a where clause, but I was wondering if there was any way you could use the value in the where clause after decoding in the selection. Basically, I have a case sorta like this

DECODE(theRow, 'P', 1,'D',2,'T',3, ... (goes on a bit)) AS theRowDecoded

And I want to select the values between what might be sent in for that row (so say between 5 and 8). Not sure why they didn't just use numbers for this column in the database (would make way more sense and easier programmatically), but oh well, gotta work with what I have.

So is there any way to use theRowDecoded in where or is there a better way to do a range? I know that DECODE is only an equals, but hoping there's a good way to do a range with decode.

You cannot use the alias in the where clause. There are a couple of alternatives.

Subquery

Make the query into a subquery an use the alias on a higher level.

SELECT
  theRowDecoded
FROM
  (SELECT
    DECODE(theRow, .....) as theRowDecoded
  FROM
    theTable)
WHERE
  theRowDecoded BETWEEN 5 AND 8

Use the original values

Perhaps better, because using the original values will also allow the use of indexes for your where clause. Also, it's shorter, not so nested, and therefor arguably more readable.

SELECT
  DECODE(theRow, .....) as theRowDecoded
FROM
  theTable
WHERE 
  theRow in ('T', 'X', 'Y', 'Z')

Virtual column

In the end, it might be better to change the table to numbers. You can make the number a function based virtual column . That way, the numeric column also exists in the table and can be used as any other column, with that difference that it's updates automatically if you update theRow .

I've not used virtual columns myself, but it should work like this:

alter table theTable
  add theRowDecoded int as generated always (decode(theRow, .....)) virtual;

Actual column

Instead of a virtual column, you can also add an extra column and keep the two in sync with a trigger. Or you can remove theRow altogether. Since that might not be so easy, depending on your abilities and rights, and the application(s) that use this database, you might consider introducing a new column, and make the old column a virtual column, so it will still be available as a read-only legacy column during a transition period in which the software is updated to use your new numeric column.

you can repeat the same expression in the field list. I don't know if you can use its alias in the where clause (you'll have to try).

what you can't do (afaik) is give an alias to an expression in the where clause and use it elsewhere.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM