SQL 服务器:SELECT 4 个非空列并将它们连接起来

SQL Server: SELECT 4 non-empty columns and concatenate them

假设我有以下设置

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

现在我正在构建一个查询,其中应包含至少有 1 个非空邮件(Mail1 或 Mail2...等)的行。并将所有非空邮件与“;”连接起来 然后填写缺失的空白字符以达到总共 163 个字符(所有 4 封邮件 + ;)

示例:

1) Mail1和Mail3所在的一行:

george@net.com;louis@net.com
(加上163-28=135个空白字符,总共163个字符)

2) Mail2、Mail3、Mail4所在的一行:

mail2@gmail.com;mail3@gmail.com;mail4@gmail.com(还有很多空格要填163)

但是当我尝试构建 Select 时它变得有点棘手,我考虑过使用 CASE WHEN THEN 子句但最终有太多的情况需要处理。连同 "fill with blank characters" 问题。

欢迎任何帮助。 提前致谢。

尚未对此进行测试,但希望它对您有用。

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

如果您的 table 有空字符串或空白字符串,您的表达式将变得有点复杂:

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

我真的不明白你为什么要将这些最多填充到 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。

我在这里假设当您说 "empty" 邮件时,您可能表示 null 或空字符串。

编辑修改为将白色 space、null 和空字符串视为相同。注意向 Joe 大声提醒我将分号放在前面。当你这样做时,你可以使用 stuff 将其替换为空白字符。 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
('Mail1@M1.Com','Mail2@M2.Com','Mail3@M3.com','Mail4@M4.com')
,(NULL,'Mail2@M2.Com','Mail3@M3.com','Mail4@M4.com')
,('Mail1@M1.Com',NULL,'Mail3@M3.com','Mail4@M4.com')
,('Mail1@M1.Com','Mail2@M2.Com',NULL,'Mail4@M4.com')
,('Mail1@M1.Com','Mail2@M2.Com','Mail3@M3.com',NULL)
,('Mail1@M1.Com',NULL,NULL,NULL)
,('Mail1@M1.Com','Mail2@M2.Com',NULL,NULL)
,(NULL,'Mail2@M2.Com',NULL,'Mail4@M4.com')
,(NULL,'Mail2@M2.Com',NULL,NULL)
,('Mail1@M1.Com',NULL,NULL,'Mail4@M4.com')
,(NULL,NULL,NULL,'Mail4@M4.com')
,(NULL,NULL,NULL,NULL)
,(NULL,NULL,NULL,'')
,('Mail1@M1.Com','',NULL,'Mail4@M4.com')
,(' ',NULL,'   ','Mail4@M4.com')
,(NULL,NULL,NULL,'   ')