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每个类别的单行,比如

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
    )
    
  • 获取每个 s 中第二高的数据:idcat

    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 rd最高的数据: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() 数据类型的多集数据类型......这可能会导致难以阅读,具体取决于您使用的程序语言。

感谢 Fernando Nunes 向IIUG 论坛推荐了这个 SQL

目前,除了复杂的 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 回答