2016-09-22 27 views
0

比方說,我有以下設置SQL服務器中:選擇4個非空列,將它們連接起來

MailsTable 
Mail1 Varchar(40) 
Mail2 Varchar(40) 
Mail3 Varchar(40) 
Mail4 Varchar(40) 

現在我建立一個查詢,應包括具有至少1郵件行,是不是空的(Mail1或Mail2 ...等)。並將所有非空郵件與';'連接起來 然後填充缺失的空白字符達到163個字符總計(所有4個郵件+;)

實施例:

1)在一排,其中MAIL1和Mail3存在:

[email protected] ; [email protected]
(和163-28 = 空白字符來填充163個總字符)

2)在一排,其中Mail2,Mail3和Mail4存在:

[email protected]; [email protected]; [email protected](和許多空白字符填充163)

但是,當我嘗試構建選擇,我想使用CASE WHEN THEN條款,但最終有太多案件需要處理。隨着「填空白字符」問題。

任何幫助,歡迎。 在此先感謝。

+0

你嘗試過什麼?您應該包含一些示例數據和預期結果。當你說填充空白字符時,你只是想要CHAR(163)還是你想要空格? – Matt

+0

我一直在用Convert(CHAR(163),column)處理填充符,但這些實際上是4列有很多不同的場景,所以我不知道如何包裝整個事情。至於數據,我會嘗試添加更多的例子。 –

+2

糟糕的餐桌設計。只有一個郵件列。 (並根據需要使用多行。) – jarlh

回答

1

我真的不明白你爲什麼要墊這些多達163個字符,但這裏的,顯示空非空地址的所有可能的組合一例:

declare @MailsTable table 
(
    RowNumber int, 
    Mail1 varchar(40), 
    Mail2 varchar(40), 
    Mail3 varchar(40), 
    Mail4 varchar(40) 
); 

insert @MailsTable values 
    (0, null, null, null, null), 
    (1, 'Addr1', null, null, null), 
    (2, null, 'Addr2', null, null), 
    (3, 'Addr1', 'Addr2', null, null), 
    (4, null, null, 'Addr3', null), 
    (5, 'Addr1', null, 'Addr3', null), 
    (6, null, 'Addr2', 'Addr3', null), 
    (7, 'Addr1', 'Addr2', 'Addr3', null), 
    (8, null, null, null, 'Addr4'), 
    (9, 'Addr1', null, null, 'Addr4'), 
    (10, null, 'Addr2', null, 'Addr4'), 
    (11, 'Addr1', 'Addr2', null, 'Addr4'), 
    (12, null, null, 'Addr3', 'Addr4'), 
    (13, 'Addr1', null, 'Addr3', 'Addr4'), 
    (14, null, 'Addr2', 'Addr3', 'Addr4'), 
    (15, 'Addr1', 'Addr2', 'Addr3', 'Addr4'); 

with ConcatenatedAddressesCTE as 
(
    select 
     RowNumber, 
     Mails = 
      case when Mail1 != '' then ';' + Mail1 else '' end + 
      case when Mail2 != '' then ';' + Mail2 else '' end + 
      case when Mail3 != '' then ';' + Mail3 else '' end + 
      case when Mail4 != '' then ';' + Mail4 else '' end 
    from 
     @MailsTable 
    where 
     Mail1 != '' or Mail2 != '' or Mail3 != '' or Mail4 != '' 
) 
select 
    RowNumber, 
    FormattedMails = substring(Mails, 2, 200) + replicate(' ', 164 - len(Mails)) 
from 
    ConcatenatedAddressesCTE; 

結果:

RowNumber FormattedMails 
1   Addr1                                        
2   Addr2                                        
3   Addr1;Addr2                                       
4   Addr3                                        
5   Addr1;Addr3                                       
6   Addr2;Addr3                                       
7   Addr1;Addr2;Addr3                                     
8   Addr4                                        
9   Addr1;Addr4                                       
10   Addr2;Addr4                                       
11   Addr1;Addr2;Addr4                                     
12   Addr3;Addr4                                       
13   Addr1;Addr3;Addr4                                     
14   Addr2;Addr3;Addr4                                     
15   Addr1;Addr2;Addr3;Addr4                                    

的CTE前綴以分號每一個非空的地址,以便它不必擔心有多少可能會出現空地址在兩個非空地址之間。這意味着它產生的每個結果都將以分號開始,這就是爲什麼查詢的最後一部分剝離最左邊的字符,以及爲什麼它在長度計算中使用164而不是163。

我在這裏假設,當你說一個「空」的郵件時,你可能意味着一個null或一個空字符串。

+0

哇,我印象深刻! (甚至沒有注意到子字符串擺脫領先;尼斯!)。此外,即時通訊很高興您將empy視爲空或「空」。不清楚這件事是我的壞處。太感謝了! –

1

沒有測試過,但希望它適合你。

SELECT ISNULL(Mail1 + ';', '') + ISNULL(Mail2 + ';', '') + ISNULL(Mail3 + ';', '') + ISNULL(Mail4 + ';', '') AS Result 
FROM MailsTable 

在表有空或空字符串表達式會變得更加複雜一些事件:

SELECT ISNULL(CASE WHEN RTRIM(Mail1) = '' THEN NULL ELSE Mail1 END + ';', '') + 
     ISNULL(CASE WHEN RTRIM(Mail2) = '' THEN NULL ELSE Mail2 END + ';', '') + 
     ISNULL(CASE WHEN RTRIM(Mail3) = '' THEN NULL ELSE Mail3 END + ';', '') + 
     ISNULL(CASE WHEN RTRIM(Mail4) = '' THEN NULL ELSE Mail4 END + ';', '') AS Result 
FROM MailsTable 

我錯過了弦填充的要求。隨着字符串填充查詢將看起來如下:

SELECT CONVERT(CHAR(163), 
     (
      LEFT(
        ISNULL(CASE WHEN RTRIM(Mail1) = '' THEN NULL ELSE Mail1 END + ';', '') + 
        ISNULL(CASE WHEN RTRIM(Mail2) = '' THEN NULL ELSE Mail2 END + ';', '') + 
        ISNULL(CASE WHEN RTRIM(Mail3) = '' THEN NULL ELSE Mail3 END + ';', '') + 
        ISNULL(CASE WHEN RTRIM(Mail4) = '' THEN NULL ELSE Mail4 END + ';', '') + SPACE(163), 163) 
       )) AS Result 
FROM MailsTable 
1

編輯修改爲處理空白,空和空字符串相同。請注意大聲呼籲Joe提醒我將分號放在前面。當你這樣做的時候,你可以用東西來替換一個空白字符。 Cast to CHAR(163)會自​​動爲您的字符串右側填充長度爲163個字符。

SELECT 
    * 
    ,CAST(
     STUFF(
      CASE WHEN COALESCE(RTRIM(Mail1),'') <> '' THEN ';' + Mail1 ELSE '' END 
      + CASE WHEN COALESCE(RTRIM(Mail2),'') <> '' THEN ';' + Mail2 ELSE '' END 
      + CASE WHEN COALESCE(RTRIM(Mail3),'') <> '' THEN ';' + Mail3 ELSE '' END 
      + CASE WHEN COALESCE(RTRIM(Mail4),'') <> '' THEN ';' + Mail4 ELSE '' END 
     ,1,1,'') 
    AS CHAR(163)) 
FROM 
    @MailsTable 
WHERE 
    COALESCE(RTRIM(Mail1),'') <> '' 
    OR COALESCE(RTRIM(Mail2),'') <> '' 
    OR COALESCE(RTRIM(Mail3),'') <> '' 
    OR COALESCE(RTRIM(Mail4),'') <> '' 

下面是測試數據:

DECLARE @MailsTable AS TABLE (Id INT IDENTITY(1,1), Mail1 VARCHAR(40), Mail2 VARCHAR(40), Mail3 VARCHAR(40), Mail4 VARCHAR(40)) 
INSERT INTO @MailsTable VALUES 
('[email protected]','[email protected]','[email protected]','[email protected]') 
,(NULL,'[email protected]','[email protected]','[email protected]') 
,('[email protected]',NULL,'[email protected]','[email protected]') 
,('[email protected]','[email protected]',NULL,'[email protected]') 
,('[email protected]','[email protected]','[email protected]',NULL) 
,('[email protected]',NULL,NULL,NULL) 
,('[email protected]','[email protected]',NULL,NULL) 
,(NULL,'[email protected]',NULL,'[email protected]') 
,(NULL,'[email protected]',NULL,NULL) 
,('[email protected]',NULL,NULL,'[email protected]') 
,(NULL,NULL,NULL,'[email protected]') 
,(NULL,NULL,NULL,NULL) 
,(NULL,NULL,NULL,'') 
,('[email protected]','',NULL,'[email protected]') 
,(' ',NULL,' ','[email protected]') 
,(NULL,NULL,NULL,' ') 
+0

謝謝馬特!我沒有澄清,通過空我的意思是空和一個空字符串(所以它不是100%給我的數據)。還是非常感謝幫助。作出+保存我的一天:D –

+0

@J_Ocampo是啊我想我的解決方案只處理了一部分空字符串。我改變了它能夠處理空白空間(crlf,tab,空格),空值和空字符串。通過竊取joes的想法來開頭說明地址;那麼你可以使用東西,擺脫主角使得它比使用另一個cte或複製日誌連接語句更整齊.... – Matt