2013-03-12 70 views
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 

而且我想最后3个id S和每个类别的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 
    ) 
    
  • 获取具有2个第二最高id S中的数据对于每个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 RD最高id对于每个数据cat

    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 11.50或以上,则存在不完美的选择使用Informix

+0

如果可以使用存储过程,它会给你的灵活性分阶段进行,参考之前的最大值。我可能会先写一个SP来检索指定cat的Max id,然后是WHERE id 2013-03-13 00:21:25

+0

不幸的是,我只能读取数据库。 – 2013-03-13 10:13:51

+0

然后我祝你好运,我所有的想法(除了将数据导出到MS SQL或Postgres的,并与热膨胀系数这样做!) – 2013-03-13 10:19:40

回答

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 
+0

尼斯的答案。我得到一些SQL语法错误,但我明白了。 '<='+'COUNT'查看存在多少更大的'id'。 – 2013-03-18 14:03:24

+0

Informix不允许在FROM子句中使用子选择,因此我使用了临时表。 – 2013-03-18 15:12:25

0

做到这一点,但也许可以提供帮助。检查波纹管末端的选择。

他们将返回一个带有char()数据类型的数据类型multiset ...其中可能会创建一个难以阅读它,这取决于您使用的程序语言。

感谢费尔南多·努涅斯谁提出这个SQL到IIUG forum

在这一刻我没有看到,除了复杂的SQLS其他选择。

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 '}