2009-12-04 58 views
1

我试图从“第一”行满足某些标准,其中“第一”是由一个硬编码的列表中定义的提取列值列值。不幸的是,我是一名SQL业余爱好者。我正在使用DB2。从列值的硬编码列表(枢轴问题?)找到的第一行

我能做到这一点低效这样的:

SELECT COALESCE(
    (SELECT COL FROM SOMETABLE WHERE X = "txt1" AND Y = "txt2" AND COL = 'A'), 
    (SELECT COL FROM SOMETABLE WHERE X = "txt1" AND Y = "txt2" AND COL = 'B'), 
    (SELECT COL FROM SOMETABLE WHERE X = "txt1" AND Y = "txt2" AND COL = 'C'), 
    (SELECT COL FROM SOMETABLE WHERE X = "txt1" AND Y = "txt2" AND COL = 'D') 
) 

这里的问题是,SOMETABLE是非常大的。所以不是我想这样做:

SELECT COALESCE(
    (SELECT COL FROM T WHERE COL = 'A'), 
    (SELECT COL FROM T WHERE COL = 'B'), 
    (SELECT COL FROM T WHERE COL = 'C'), 
    (SELECT COL FROM T WHERE COL = 'D') 
) 
FROM 
    (SELECT COL FROM SOMETABLE WHERE X = "txt1" AND Y = "txt2") AS T 

这是无效的,因为我不能引用的T台。

假设高于T包含下列行:

'E' 
'B' 
'D' 

然后我想挑“B”,因为它是在COALESCE语句中指定的第一个值。

我知道我可以做这样的事情得到一定程度接近我想要的东西:

SELECT 
    (CASE COL WHEN 'A' THEN COL ELSE NULL END), 
    (CASE COL WHEN 'B' THEN COL ELSE NULL END), 
    (CASE COL WHEN 'C' THEN COL ELSE NULL END), 
    (CASE COL WHEN 'D' THEN COL ELSE NULL END) 
FROM 
    (SELECT COL FROM SOMETABLE WHERE X = "txt1" AND Y = "txt2") AS T 

这样产生的结果是:

- - - - 
- - - D 
- B - - 

现在我想聚集或“扁平化”到这个单排,像这样:

- B - D 

然后,我会简单地凝聚在列。

任何建议,将不胜感激!

回答

0

我想我找到了解决方案。

SELECT COALESCE(
    MAX(CASE COL WHEN 'A' THEN COL ELSE NULL END), 
    MAX(CASE COL WHEN 'B' THEN COL ELSE NULL END), 
    MAX(CASE COL WHEN 'C' THEN COL ELSE NULL END), 
    MAX(CASE COL WHEN 'D' THEN COL ELSE NULL END)) 
FROM 
    (SELECT COL FROM SOMETABLE WHERE X = "txt1" AND Y = "txt2") AS T 

请让我知道这是愚蠢的还是错误的。

0

如果我正确理解你的问题,你可以

SELECT COALESCE( 
    (SELECT COL FROM T WHERE COL = 'A'), 
    (SELECT COL FROM T WHERE COL = 'B'), 
    (SELECT COL FROM T WHERE COL = 'C'), 
    (SELECT COL FROM T WHERE COL = 'D')) 
FROM (SELECT COL FROM SOMETABLE WHERE X = "txt1" AND Y = "txt2") AS T 

转换为CTE为下:

WITH T AS (
    SELECT COL FROM SOMETABLE WHERE X = "txt1" AND Y = "txt2" 
) 
SELECT COALESCE( 
    (SELECT COL FROM T WHERE COL = 'A'), 
    (SELECT COL FROM T WHERE COL = 'B'), 
    (SELECT COL FROM T WHERE COL = 'C'), 
    (SELECT COL FROM T WHERE COL = 'D')) 
FROM T; 

或类似这样的东西。我无法测试它,因为我没有DB2数据库。

+0

对,这样会更好。不幸的是,似乎在我查询的Db2/400系统上不支持“with”语句。 – Einar 2009-12-08 11:06:01

+0

对不起,在DB2v9.1中支持(我曾经使用过的一个 ) – 2009-12-08 16:09:13

1

排序提供您的硬编码值,以便适用于您的问题,那么:

SELECT COL 
FROM SOMETABLE 
WHERE X = "txt1" 
AND Y = "txt2" 
ORDER BY col 
fetch first 1 rows only 
0

你是非常接近这个...

SELECT COALESCE(
    MAX(CASE COL WHEN 'A' THEN COL ELSE NULL END), 
    MAX(CASE COL WHEN 'B' THEN COL ELSE NULL END), 
    MAX(CASE COL WHEN 'C' THEN COL ELSE NULL END), 
    MAX(CASE COL WHEN 'D' THEN COL ELSE NULL END)) 
FROM 
    (SELECT COL FROM SOMETABLE WHERE X = "txt1" AND Y = "txt2") AS T 

你不需要聚结(可以” t不需要子查询(where子句总是先评估)

SELECT MAX(CASE WHEN COL = 'A' THEN COL ELSE NULL END) AS A, 
     MAX(CASE WHEN COL = 'B' THEN COL ELSE NULL END) AS B, 
     MAX(CASE WHEN COL = 'C' THEN COL ELSE NULL END) AS C, 
     MAX(CASE WHEN COL = 'D' THEN COL ELSE NULL END) AS D 
    FROM SOMETABLE 
WHERE X = "txt1" 
    AND Y = "txt2" 

某些数据库支持执行类似(但不完全相同)事情的ANSI SQL标准PIVOT功能。这听起来不像DB2/400有许多高级功能。

Joe

+0

对,感谢您的简化!我一定会删除无意义的子查询。 我觉得我确实需要合并。通过合并,我得到了我想要的结果('B'),没有它我得到(' - ''B'' - ''D')。 通过添加WH IN子句,说COL IN('A','B','C','D'),我会受益于性能吗?毕竟,可能会有满足X =“txt1 AND Y =”txt2“的行,比如说COL ='E' – Einar 2009-12-09 08:02:22

+0

啊,知道了,我以为你想要' - ','B',' - ','D '是的,增加一个进一步的过滤器*可以*加快速度。 – 2009-12-09 08:53:22

+0

再次感谢,我会尝试并运行一些性能测试。 – Einar 2009-12-09 09:14:46