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,' ')
假设我有以下设置
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,' ')