简体   繁体   中英

Oracle SQL “meta” query for records which have specific column values

I'd like to get all the records from a huge table where any of the number columns countains a value greater than 0 . What's the best way to do it?

Eg:

/* table structure*/
create table sometable (id number, 
                        somestring varchar2(12),
                        some_amount_1 number(17,3),
                        some_amount_2 number(17,3),
                        some_amount_3 number(17,3),
                        ...
                        some_amount_xxx number(17,3));
/* "xxx" > 100, and yeah I did not designed that table structure... */

And I want any row where any of the some_amount_n > 0 (even better solution is to add a field in the first place to show which field(s) are greater than zero).

I know I can write this with a huge some_amount_1 > 0 OR some_amount_2 > 0 OR ... block (and the field names with some case when but is there should be some more elegant solution, isn't there?

Possible solutions:

  1. Normalize the table. You said you are not allowed to. Try to convince those that forbid such a change by explaining the benefits (performance, ease of writing queries, etc).

  2. Write the huge ugly OR query. You could also print it along with the version of the query for the normalized tables. Add performance tests (you are allowed to create another test table or database, I hope.)

  3. Write a program (either in PL/SQL or in another procedural language) that produces the horrible OR query. (Again, print along with the elegant version)

  4. Add a new column, say called Any_x_bigger_than_zero which is automatically filled with either 0 or 1 via a trigger (that uses a huge ugly OR ). Then you just need to check: WHERE Test_x_bigger_than_zero = 1 to see if any of the rows is > 0

  5. Similar to previous but even better, create a materialized view with such a column.

First, create a table to sort the data into something more easily read from...something simple like id,column_name,column_value. You'll have to bear with me, been a while since I've operated in oracle, so this is heavy pseudo code at best:

Quick dynamic sql blurb...you can set a variable to a sql statement and then execute that variable. There are some security risks and it's possible this feature is disabled in your environment...so confirm you can run this first. Declare a variable, set the variable to 'select 1' and then use 'execute immediate' to execute the sql stored in your variable.

set var = 'select id, ''some_amount_' || 1  || '', some_amount || 1 || ' from table where some_amount_' || 1  || ' <> 0'

Assuming I've got my oracle syntax right...( pipe is append right? I believe a 3 single quote as ''' should result in one ' when in a variable too, you may have to trial and error this line until you have the var set to):

select id, 'some_amount_1',some_amount_1
from table
where some_amount_1 <> 0

This should select the ID and the value in some_amount_1 for each id in your database. You can turn this into an insert statement pretty easily.

I'm assuming some_amount_xxx has an upper limit...next trick is to loop this giant statement. Once again, horrible pseudo code:

declare sql_string
declare i and set to 1
for i = 1 to xxx (whatever your xxx is)
set sql_string to the first set var statement we made, replacing the '1' with the i var here.
execute sql
increment i
loop

Hopefully it makes sense...it's one of the very few scenarios you would ever want to loop dynamic sql on. Now you have a relatively straight forward table to read from and this should be a relatively easy query from here

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