2013-02-28 66 views
1

我有一個名爲'transactions'的數據庫表有多個列。對於每一個交易行,我需要從一個指定的列表產生,每列一排出口選擇列進行導出

交易表

ID, DoNotEmail, DoNotMail, DoNotPhone, DoNotSMS 
1000, true, false,  true,  true

以下規則需要申請。

DoNotEmail被設置後輸出 'DNE'

DoNotMail被設置後輸出 'DNM'

DoNotPhone被設置後輸出 'DNP'

DoNotSMS被設置後輸出 'DNS'

出口需要的樣子:

ID, Suppressions 
1000, DNE 
1000, DNP 
1000, DNS

林變得非常困惑,唯一能讓它工作的方式對於每個列的插入語句進入兩個臨時表非常可怕。 Urgh。

請問這可能嗎?

感謝您的任何幫助。

Darren

p.s.對格式化抱歉。

+0

你使用的是什麼rdbms? – Taryn 2013-02-28 16:04:31

回答

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 Fiddle Demo

+0

+1擊敗我,刪除我重複的答案 – Lamak 2013-02-28 15:38:15

+0

+1正確使用union all。 – 2013-02-28 15:48:00

+0

嗨,我得到了30多欄! – 2013-02-28 16:03:47

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 
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 with Demo

+0

@DarrenRhymer看到我的編輯,我包括一個版本,使用'unpivot'功能。這將最小化獲得結果所需的代碼行。 – Taryn 2013-02-28 16:27:47

1

一個CROSS 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 Fiddle

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

+1我喜歡'交叉應用'與'價值'版本。 – Taryn 2013-02-28 16:29:53

+0

@bluefeet是的,它看起來不錯。查看查詢計劃,它與兩個版本的操作都差不多。一個表連接掃描四行不間斷掃描,所以應該沒有真正的性能差異。 – 2013-02-28 16:35:06

+0

感謝所有的答案,但我實現了這一個,它的工作原理。謝謝Mikael – 2013-03-04 13:18:00