使用CASE表达式

时间:2018-01-31 01:45:16

标签: sql postgresql netezza

给出表t1如下

+---------+----------+
| bin_val |  bin_cnt |
+---------+----------+
|       0 |        2 |
|       4 |       10 |
|       8 |       15 |
|      12 |       12 |
|      16 |        6 |
|      20 |        1 |
+---------+----------+

我需要在Netezza的表bin_vals_selected中创建临时表t1,我的操作如下:

CREATE TEMP TABLE bin_vals_selected as (
  -- statements
) DISTRIBUTE ON RANDOM;

我需要编写语句以bin_valt1有条件地基于我的生产界面中可用的变量$bin_selected选择bin_vals_selected(在SQL传递之前它是一个简单的字符串替换到Netezza执行)。

我在临时表$bin_selected中需要的内容如下:

'all' = bin_vals_selected时,bin_val应包含来自t1的所有不同SELECT DISTINCT bin_val as bin_selected FROM t1 。对此的陈述如下。

$bin_selected

'first' = bin_vals_selected时,bin_val应包含来自t1的{​​{1}} bin_count。对此的陈述如下。

SELECT bin_val as bin_selected FROM t1 ORDER BY bin_cnt DESC LIMIT 1

$bin_selected = 'second'时,bin_vals_selected应包含来自bin_val的{​​{1}},其中t1排名第二bin_count。我不确定如何为此写声明。

我正在使用CASE表达式来接近这个,以根据变量$bin_selected的值创建表格 - 但是它不起作用。

CREATE TEMP TABLE bin_vals_selected AS
(
  SELECT * FROM (
    CASE 
      WHEN $bin_selected = 'all' THEN
        (SELECT DISTINCT bin_val AS bin_selected FROM t1 AS a)
      WHEN $bin_selected = 'first' THEN
        (SELECT bin_val AS bin_selected FROM t1 AS a ORDER BY bin_cnt DESC LIMIT 1 )
    END
  )
) DISTRIBUTE ON RANDOM;

虽然上面的语法适用于Netezza为中心(大部分类似于Postgres),但Postgres解决方案也会有所帮助,因为我有本地Postgres实例可以试用。

2 个答案:

答案 0 :(得分:1)

我首先使用group by,然后使用条件。你可以这样做:

select bin_val
from (select bin_val, ,  -- not really needed
             row_number() over (order by bin_cnt desc) as seqnum
      from t1
     ) t
where ($bin_selected = 'all') or
      ($bin_selected = 'first' and seqnum = 1) or
      ($bin_selected = 'second' and seqnum = 2);

如果您希望在垃圾箱具有相同计数时允许关联,请使用dense_rank()而不是row_number()

答案 1 :(得分:0)

如果你真的必须使用单个SQL,你可以使用类似于:

的UNION
SELECT DISTINCT bin_val as bin_selected 
FROM t1
WHERE 'all' = $bin_selected

UNION ALL

SELECT bin_val as bin_selected
FROM (
  SELECT bin_val, RANK() OVER(ORDER BY bin_cnt DESC) AS BinCountRank
  FROM t1
) src
WHERE BinCountRank = 1
AND 'first' = $bin_selected

UNION ALL

SELECT bin_val as bin_selected
FROM (
  SELECT bin_val, RANK() OVER(ORDER BY bin_cnt DESC) AS BinCountRank
  FROM t1
) src
WHERE BinCountRank = 2
AND 'second' = $bin_selected

效率不高,但它应该可以解决问题。它确实为您的源查询提供了灵活性。你可能不得不乱用RANK()处理任何关系。它还假定您的UNION字符串中的每个查询都返回具有相同数据类型的完全相同的#列。

对于你的情况,我使用戈登的答案......它更清洁,更快。