0

私は次のようなテーブルを持っています

id      cat     data
--------------------
1       1       foo
2       1       bar
3       1       baz
4       2       some
5       2       random
6       3       Data 1
7       2       data
8       3       Data 2
9       3       Data 3

そして、私は最後の3id秒間と、次dataのような1行の各カテゴリが必要です。

cat     id1     data1   id2     data2   id3     data3
-----------------------------------------------------
1       1       foo     2       bar     3       baz
2       4       some    5       random  7       data
3       6       Data 1  8       Data 2  9       Data 3

私はすでに次のことを試しました:

  • idそれぞれのデータが最も高いデータを取得しますcat

    SELECT id, data FROM tbl t1 WHERE EXISTS (
        SELECT 1 FROM tbl t2 WHERE t1.cat = t2.cat 
        GROUP BY t2.cat HAVING MAX(t2.id) = t1.id
    )
    
  • それぞれについて2番目に高いidsを持つデータを取得しますcat

    SELECT id, data FROM tbl t1 WHERE EXISTS (
        SELECT 1 FROM tbl t2 WHERE t1.cat = t2.cat AND NOT EXISTS (
            -- Not the highest value
            SELECT 1 FROM tbl t3 WHERE t1.cat = t3.cat GROUP BY t3.cat
            HAVING MAX(t3.id) = t2.id
        ) GROUP BY t2.cat HAVING MAX(t2.id) = t1.id
    )
    
  • それぞれについて3番目に高いデータを取得します。idcat

    SELECT id, data FROM tbl t1 WHERE EXISTS (
        SELECT 1 FROM tbl t2 WHERE t1.cat = t2.cat AND NOT EXISTS (
            -- id is not 2nd highest
            SELECT 1 FROM tbl t3 WHERE t1.cat = t3.cat AND NOT EXISTS (
                -- id is not the highest
                SELECT 1 FROM tbl t4 WHERE t1.cat = t4.cat GROUP BY t4.cat
                HAVING MAX(t4.id) = t3.id
            ) GROUP BY t3.cat HAVING MAX(t3.id) = t2.id
        ) AND NOT EXIST (
            -- not the highest id
            SELECT 1 FROM tbl t5 WHERE t1.cat = t5.cat GROUP BY t5.cat
            HAVING MAX(t5.id) = t2.id
        ) GROUP BY t2.cat HAVING MAX(t2.id) = t1.id
    )
    

そして今、すべてに参加します。しかし、もっと良い解決策があると思います。それは何ですか?

PS:私はInformixでそれをしなければなりません

4

2 に答える 2

1

私の答えではありませんが、私の同僚がこれを思いつきました:

create temp table t(
    id      smallint,
    cat     smallint,
    data    char(10)
) with no log;

insert into t values (1, 1, "foo");
insert into t values (2, 1, "bar");
insert into t values (3, 1, "baz");
insert into t values (4, 2, "some");
insert into t values (5, 2, "random");
insert into t values (6, 3, "Data 1");
insert into t values (7, 2, "data");
insert into t values (8, 3, "Data 2");
insert into t values (9, 3, "Data 3");
insert into t values (10, 4, "some");
insert into t values (11, 4, "more");
insert into t values (12, 4, "random");
insert into t values (13, 4, "data");
insert into t values (14, 4, "for");
insert into t values (15, 4, "testing");
insert into t values (16, 5, "one");

select
   cat,
   max(case when cnt = 3 then id end) as id1,
   max(case when cnt = 2 then id end) as id2,
   max(case when cnt = 1 then id end) as id3,
   max(case when cnt = 3 then data end) as data1,
   max(case when cnt = 2 then data end) as data2,
   max(case when cnt = 1 then data end) as data3
from
   (
       select
          a.cat,
          a.id,
          a.data,
          count(*) as cnt
       from
          t a,
          t b
       where
          a.cat = b.cat and
          a.id <= b.id
       group by
          a.id,
          a.cat,
          a.data
       having
          count(*) <= 3
   )
group by
    1
order by
    1;

cat    id1    id2    id3 data1      data2      data3

  1      1      2      3 foo        bar        baz
  2      4      5      7 some       random     data
  3      6      8      9 Data 1     Data 2     Data 3
  4     13     14     15 data       for        testing
  5                   16                       one
于 2013-03-14T07:57:32.850 に答える
0

Informix 11.50以降を使用している場合、完全ではないオプションがありますが、おそらく役立つ可能性があります。以下の最後の選択を確認してください。

それらはchar()データ型を持つマルチセットデータ型を返します...使用しているプログラム言語によっては、おそらくそれを読むのが難しいでしょう。

このSQLをIIUGフォーラムに提案してくれたFernandoNunesに感謝します

現時点では、複雑なSQL以外の選択肢はありません。

drop table teste; 
create temp table teste ( id smallint, cat smallint, data char(10)); 
insert into teste values ( 1, 1, 'foo ' ); 
insert into teste values ( 2, 1, 'bar ' ); 
insert into teste values ( 3, 1, 'baz ' ); 
insert into teste values ( 4, 2, 'some ' ); 
insert into teste values ( 5, 2, 'random ' ); 
insert into teste values ( 6, 3, 'Data 1 ' ); 
insert into teste values ( 7, 2, 'data ' ); 
insert into teste values ( 8, 3, 'Data 2 ' ); 
insert into teste values ( 9, 3, 'Data 3 ' ); 
insert into teste values ( 10, 3, 'Data 4 ' );

select * from teste; 
select ms.* 
from 
( 
SELECT MULTISET( SELECT ITEM t.id || ',' || t.cat || ',' || t.data m1 FROM 
teste t WHERE t.cat = tout.cat) FROM (SELECT unique cat from teste) tout 
) msdrop table teste; 

戻ります :

expression  MULTISET{'1,1,foo       ','2,1,bar       ','3,1,baz       '}
expression  MULTISET{'4,2,some      ','5,2,random    ','7,2,data      '}
expression  MULTISET{'6,3,Data 1    ','8,3,Data 2    ','9,3,Data 3    '}
于 2013-03-13T15:38:19.943 に答える