1

我有一个名为“事务”的数据库表,其中包含多个列。对于每个交易行,我需要从指定列表中生成每列一行的导出

交易表

ID、DoNotEmail、DoNotMail、DoNotPhone、DoNotSMS
1000,真,假,真,真

以下规则需要适用。

设置 DoNotEmail 然后输出 'DNE'

设置 DoNotMail 然后输出 'DNM'

设置 DoNotPhone 然后输出 'DNP'

设置 DoNotSMS 然后输出“DNS”

导出需要如下所示:

ID,抑制
1000, DNE
1000,DNP
1000,DNS

我真的很困惑,我能让它工作的唯一方法是把每列插入两个临时表的插入语句真的很糟糕。呃。

请问这可能吗?

谢谢你的帮助。

达伦

ps 对格式感到抱歉。

4

5 回答 5

6

可以这样写的另一种方式是:

SELECT id,
  case col 
    when 'DoNotEmail' then 'DNE'
    when 'DoNotMail' then 'DNM'
    when 'DoNotPhone' then 'DNP'
    when 'DoNotSMS' then 'DNS'
  end Suppressions
FROM 
(
  SELECT t.ID,
    s.col,
    CASE s.col
      WHEN 'DoNotEmail' THEN DoNotEmail
      WHEN 'DoNotMail' THEN DoNotMail
      WHEN 'DoNotPhone' THEN DoNotPhone
      WHEN 'DoNotSMS' THEN DoNotSMS
    END AS DATA
  FROM Transactions t
  CROSS JOIN 
  (
    SELECT 'DoNotEmail' AS col
    UNION ALL SELECT 'DoNotMail'
    UNION ALL SELECT 'DoNotPhone'
    UNION ALL SELECT 'DoNotSMS'
  ) s
) s
where data = 'true';

请参阅SQL Fiddle with Demo

由于您使用的是 SQL Server,因此您可以实现该UNPIVOT功能:

select id,
  case col 
    when 'DoNotEmail' then 'DNE'
    when 'DoNotMail' then 'DNM'
    when 'DoNotPhone' then 'DNP'
    when 'DoNotSMS' then 'DNS'
  end Suppressions
from Transactions
unpivot
(
  value 
  for col in ([DoNotEmail], [DoNotMail], [DoNotPhone], [DoNotSMS])
) piv
where value = 'true'

请参阅带有演示的 SQL Fiddle

于 2013-02-28T15:49:41.560 回答
6

如果您只有四列,这可能会起作用:

SELECT id, 
       'DNE' AS Suppressions 
FROM   transactions 
WHERE  donotemail = 'true' 
UNION ALL 
SELECT id, 
       'DNM' AS Suppressions 
FROM   transactions 
WHERE  donotmail = 'true' 
UNION ALL 
SELECT id, 
       'DNP' AS Suppressions 
FROM   transactions 
WHERE  donotphone = 'true' 
UNION ALL 
SELECT id, 
       'DNS' AS Suppressions 
FROM   transactions 
WHERE  donotsms = 'true' 

SQL 小提琴演示

于 2013-02-28T15:35:55.117 回答
4

这适用于 SQL Server 2008 或更高版本。如果需要,它也可以修改为在 SQL Server 2005 上工作。

select T1.ID,
       T2.Name
from Transactions as T1
  cross apply (values (DoNotEmail, 'DNE'), 
                      (DoNotMail,  'DNM'), 
                      (DoNotPhone, 'DNP'), 
                      (DoNotSMS,   'DNS')
              ) as T2(Value, Name)
where T2.Value = 'true' 
于 2013-02-28T16:21:58.710 回答
1

四记录表上的ACROSS JOIN可以节省扫描表四次。bluefeet 首先使用此 (+1) 发布了答案。这是使用 Oracle 的类似版本。

SELECT id, Suppressions FROM
(
  SELECT id, 
     CASE 
        WHEN Col = 1 AND donotemail = 'true' THEN 'DNE'
        WHEN Col = 2 AND donotmail  = 'true' THEN 'DNM'
        WHEN Col = 3 AND donotphone = 'true' THEN 'DNP'
        WHEN Col = 4 AND donotsms   = 'true' THEN 'DNS'
        ELSE NULL
     END Suppressions 
  FROM Transactions
  CROSS JOIN (SELECT Level Col FROM dual CONNECT BY Level <=4)
)
WHERE Suppressions IS NOT NULL;

SQL小提琴

于 2013-02-28T16:16:46.527 回答
0
select ID, 'DNE' as 'Suppressions'
from transactions
where DoNotEmail = 'true'
UNION ALL
select ID, 'DNM' as 'Suppressions'
from transactions
where DoNotMail = 'true'
UNION ALL
select ID, 'DNS' as 'Suppressions'
from transactions
where DoNotPhone = 'true'
UNION ALL
select ID, 'DNE' as 'Suppressions'
from transactions
where DoNotSMS = 'true'
order by ID
于 2013-02-28T15:37:40.187 回答