如何删除联盟?

时间:2017-01-30 10:57:48

标签: sql sql-server

我试图删除union all以进行后续查询。

DECLARE @TEMP TABLE (ID INT,DESCR VARCHAR(20))
            INSERT INTO @TEMP
            SELECT 1,'A'
            UNION 
            SELECT 2,'B'
            UNION 
            SELECT 3,'C'
            UNION 
            SELECT 4,'D'

            SELECT DESCR,ID FROM @TEMP
            WHERE DESCR NOT IN ('A','B')
            UNION ALL
            SELECT 'A+B',SUM(ID) FROM @TEMP
            WHERE DESCR IN ('A','B')

是否有人建议使用而不是联合所有

3 个答案:

答案 0 :(得分:1)

您可以将group bycase

一起使用
SELECT (CASE WHEN DESCR IN ('A', 'B') THEN 'AB'
             ELSE DESCR
        END) as DESCR, SUM(ID) as ID FROM @TEMP
FROM @TEMP
GROUP BY (CASE WHEN DESCR IN ('A', 'B') THEN 'AB'
               ELSE DESCR
          END);

这确实有两个重要的假设:

  • DESCR是唯一的,至少对于不包含'A''B'的行。
  • 'AB'不在数据中。

如果这些是真的,你仍然可以做你想要的,但查询可能会更复杂一些(并且表可能需要一个唯一的id)。

答案 1 :(得分:1)

如果保证DESCR在表中不能为空,则没有NOT IN问题,我们不需要任何额外的空值处理来模仿它。

你要做的是构建伪组。每个非A / B记录的“组”和所有A / B记录的真实组:

select 
  max(case when descr in ('A','B') then 'A+B' else descr end) as descr, 
  sum(id) as id
from @temp
group by 
  case when descr in ('A','B') then 'A' else descr end,
  case when descr in ('A','B') then 0 else id end;

此伪分组仅在表中没有重复时才起作用(例如,E / 5的两个记录)。如果有,那么我们必须动态生成一个唯一的密钥。

编辑:为了完整起见:如果表中可能存在重复项,我们需要一个唯一标识符。一个简单的解决方案是使用未记录的%%physloc%%。 (另一种方法是从派生表中选择我们用ROW_NUMBER创建行号。)

group by 
  case when descr in ('A','B') then 'A' else descr end,
  case when descr in ('A','B') then 0 else id end,
  case when descr in ('A','B') then 0 else %%physloc%% end;

答案 2 :(得分:0)