Pregunta


I am using Oracle 9i SQL database.I want to write a query like this

select
id_process_inst,<br>
max(case when id_data=34756 then value_text end),<br>
max(case when id_data=34760 then value_text end),<br>
max(case when id_data=34793 then value_text end),<br>
max(case when id_data=34792 then value_text end),<br>
max(case when id_data=34790 then value_text end),<br>
max(case when id_data=34761 then value_text end),<br>
max(case when id_data=34791 then value_text end),<br>
max(case when id_data=34766 then value_text end),<br>
max(case when id_data=34778 then value_text end),<br>
max(case when id_data=34767 then value_text end),<br>
m....<br>
from<br>
(<br>
select <br>
procreldata.id_inst,<br>
dataset.value_text,<br>
procreldata.id_data<br>
from wfdata procreldata<br>
inner join wfvalue dataset<br>
on dataset.id_data= procreldata.id_data<br>
where procreldata.id_inst=177262<br>
)<br>
group by id_inst;<br>

Whenever I try execute this query, I am getting "Sort key too long " error.I guess it is because I am using around 32 max functions in this query.
Kindly help me to solve this problem.
Thank you in advance.

¿Fue útil?

Solución

The Ask Tom article I linked to suggests this is a problem with the data values as well as the number of the columns, and that does seem to be the case for the example shown there; but in this case it is apparently just the number of columns.

This is a real hack but seems to work. Here t42 effectively represents the result of the join between your real tables. If I create that dummy table and add a few rows with minimal data:

create table t42 (inst_id number, id_data number, value_text varchar2(4000));

insert into t42 values (1, 1, 'w');
insert into t42 values (1, 2, 'x');
insert into t42 values (1, 3, 'y');
insert into t42 values (1, 4, 'z');

Then this still fails:

select max(case when id_data = 1 then value_text end),
  max(case when id_data = 2 then value_text end),
  max(case when id_data = 3 then value_text end),
  max(case when id_data = 4 then value_text end),
  max(case when id_data = 5 then value_text end),
  max(case when id_data = 6 then value_text end),
  max(case when id_data = 7 then value_text end),
  max(case when id_data = 8 then value_text end),
  max(case when id_data = 9 then value_text end),
  max(case when id_data = 10 then value_text end),
  max(case when id_data = 11 then value_text end),
  max(case when id_data = 12 then value_text end),
  max(case when id_data = 13 then value_text end),
  max(case when id_data = 14 then value_text end),
  max(case when id_data = 15 then value_text end),
  max(case when id_data = 16 then value_text end)
from t42
group by inst_id;

from t42
     *
ERROR at line 17:
ORA-01467: sort key too long

I only need 16 aggregate expressions, which I guess is still related to my block size, which is 2k in the only 9i database I still have around. If you need 32 columns to get the error then I'd guess your block size is 4k. Not sure that really matter unless you can increase it.

After a bit of experimentation this is the first alternative that I've found to work:

with t as (
  select inst_id, id_data,
    case when id_data = 1 then value_text end as x1,
    case when id_data = 2 then value_text end as x2,
    case when id_data = 3 then value_text end as x3,
    case when id_data = 4 then value_text end as x4,
    case when id_data = 5 then value_text end as x5,
    case when id_data = 6 then value_text end as x6,
    case when id_data = 7 then value_text end as x7,
    case when id_data = 8 then value_text end as x8,
    case when id_data = 9 then value_text end as x9,
    case when id_data = 10 then value_text end as x10,
    case when id_data = 11 then value_text end as x11,
    case when id_data = 12 then value_text end as x12,
    case when id_data = 13 then value_text end as x13,
    case when id_data = 14 then value_text end as x14,
    case when id_data = 15 then value_text end as x15,
    case when id_data = 16 then value_text end as x16
  from t42
)
select (select max(x1) from t t2 where t2.inst_id = t.inst_id),
  (select max(x2) from t t2 where t2.inst_id = t.inst_id),
  (select max(x3) from t t2 where t2.inst_id = t.inst_id),
  (select max(x4) from t t2 where t2.inst_id = t.inst_id),
  (select max(x5) from t t2 where t2.inst_id = t.inst_id),
  (select max(x6) from t t2 where t2.inst_id = t.inst_id),
  (select max(x7) from t t2 where t2.inst_id = t.inst_id),
  (select max(x8) from t t2 where t2.inst_id = t.inst_id),
  (select max(x9) from t t2 where t2.inst_id = t.inst_id),
  (select max(x10) from t t2 where t2.inst_id = t.inst_id),
  (select max(x11) from t t2 where t2.inst_id = t.inst_id),
  (select max(x12) from t t2 where t2.inst_id = t.inst_id),
  (select max(x13) from t t2 where t2.inst_id = t.inst_id),
  (select max(x14) from t t2 where t2.inst_id = t.inst_id),
  (select max(x15) from t t2 where t2.inst_id = t.inst_id),
  (select max(x16) from t t2 where t2.inst_id = t.inst_id)
from t
group by inst_id;

(SEL (SEL (SEL (SEL (SEL (SEL (SEL (SEL (SEL (SEL (SEL (SEL (SEL (SEL (SEL (SEL
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
w    x    y    z

All the self-joins are painful, but at least they are on the result set from your main query, so you're still only hitting your real tables once - the rest just needs enough memory to manage all the data that brings back.

Since there is no aggregation happening in the main query now, only in the subqueries, it's perhaps clearer to use distinct rather than group by, though the effect is the same:

...
select distinct inst_id,
  (select max(x1) from t t2 where t2.inst_id = t.inst_id),
  ...
  (select max(x16) from t t2 where t2.inst_id = t.inst_id)
from t;

This is just a demonstration. Where I've used t42 as a place-holder with fake data, put your original query back in, and add as many aggregates as you need; so within the with clause:

with t as (
   select inst_id, id_data,
    case when id_data = 34756 then value_text end as x1,
    ...
    case when id_data = 34999 then value_text end as x32
  from (
    select procreldata.id_inst,
    dataset.value_text,
    procreldata.id_data
    from wfdata procreldata
    inner join wfvalue dataset
    on dataset.id_data= procreldata.id_data
    where procreldata.id_inst=177262
  )
)
select distinct inst_id,
  (select max(x1) from t t2 where t2.inst_id = t.inst_id),
  ...
  (select max(x32) from t t2 where t2.inst_id = t.inst_id)
from t;

I'm not saying it's pretty, of course...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top