SQL - 如果缺失则添加一个值
SQL - Prepend a value if missing
Code/data:
DECLARE @T TABLE
(
[Col1] VARCHAR(20)
, [RowNum] INT
) ;
INSERT INTO @T
VALUES
( N'second', 1 )
, ( N'fifth', 4 )
, ( N'fourth', 3 )
--, ( N'zzz', 1 )
, ( N'third', 2 )
---- OR when "zzz" is part of this list
--VALUES
-- ( N'second', 2 )
-- , ( N'fifth', 5 )
-- , ( N'fourth', 4 )
-- , ( N'zzz', 1 )
-- , ( N'third', 3 )
SELECT STUFF ((
SELECT ',' + [SQ].[Col1]
FROM
(
SELECT N'zzz' AS [Col1]
, 1 AS [RowNum]
UNION
SELECT [Col1]
, [RowNum]
FROM @T
) AS [SQ]
FOR XML PATH ( '' ), TYPE
).[value] ( '.', 'varchar(MAX)' ), 1, 1, ''
) ;
当前输出:
fifth,fourth,second,third,zzz
目标:
如果在联合的第二部分中缺失,则在输出字符串中添加 "zzz," 并且这些值应根据联合第二部分中定义的 [rownum] 字段中指定的值按 ASC 顺序排列。如果 "zzz" 已经存在于输入的第二部分(在这种情况下它将始终为 RowNum 1),它应该 return 它只作为第一个值出现一次。
预期输出:
zzz,second,third,fourth,fifth
由于我在创建此 post 时出错,更新了要求。更新 code/data 表示更准确的场景。请注意 UNION 第二部分的 RowNum seq,它也是从 1 开始的,但是这次,它可能与 "zzz" 相关联,也可能不相关联。基本上,我想在前面加上 "zzz" 在逗号分隔和有序输出中(如果不存在)。
希望以下内容对您有所帮助。
SELECT ',' + [SQ].[Col1]
FROM
(
SELECT N'first' AS [Col1],1 AS [RowNum]
UNION
SELECT [ABC].[Col1],[ABC].[RowNum]
FROM
(
VALUES
( N'second', 2 )
, ( N'fifth', 5 )
, ( N'fourth', 4 )
--, ( N'first', 1 )
, ( N'third', 3 )
) AS [ABC] ( [Col1], [RowNum] )
) AS [SQ]
ORDER BY [RowNum]
FOR XML PATH ( '' ), TYPE
).[value] ( '.', 'varchar(MAX)' ), 1, 1, ''
) ;
Returns一个输出
第一,第二,第三,第四,第五
常用 Table 表达式 (CTE) 提供了一种将查询分解为更简单步骤的简便方法。请注意,您可以通过切换出最后的select
语句来查看每一步的结果。
with
Assortment as (
-- Start with the "input" rows.
select Col1, RowNum
from ( values ( N'second', 2 ), ( N'fifth', 5 ), ( N'fourth', 4 ),
-- ( N'first', 1 ),
( N'third', 3 ) ) ABC ( Col1, RowNum ) ),
ExtendedAssortment as (
-- Conditionally add "first".
select Col1, RowNum
from Assortment
union all -- Do not remove duplicate rows.
select N'first', 1
where not exists ( select 42 from Assortment where Col1 = N'first' ) )
-- Output the result.
-- Intermediate results may be seen by uncommenting one of the alternate select statements.
-- select * from Assortment;
-- select * from ExtendedAssortment;
select Stuff(
( select N',' + Col1 from ExtendedAssortment order by RowNum for XML path(N''), type).value( N'.[1]', 'NVarChar(max)' ),
1, 1, N'' ) as List;
可以使用输入表执行相同的逻辑:
-- Rows to be included in the comma delimited string.
declare @Input as Table ( Col1 NVarChar(20), RowNum Int );
insert into @Input ( Col1, RowNum ) values
( N'second', 2 ), ( N'fifth', 5 ),
--( N'ZZZ', 17 ), -- Test row.
( N'fourth', 4 ), ( N'third', 3 );
select * from @Input;
-- Mandatory value that must appear in the result. One row only.
declare @Mandatory as Table ( Col1 NVarChar(20), RowNum Int );
-- By using the maximum negative value for an Int this value will be prepended
-- (unless other rows happen to have the same RowNum value).
insert into @Mandatory ( Col1, RowNum ) values ( N'ZZZ', -2147483648 );
select * from @Mandatory;
-- Process the data.
with
AllRows as (
select Col1, RowNum
from @Input
union all
select Col1, RowNum
from @Mandatory
where not exists ( select 42 from @Mandatory as M inner join @Input as I on M.Col1 = I.Col1 ) )
-- Output the result.
-- Intermediate results may be seen by uncommenting the alternate select statement.
--select * from AllRows;
select Stuff(
( select N',' + Col1 from AllRows order by RowNum for XML path(N''), type).value( N'.[1]', 'NVarChar(max)' ),
1, 1, N'' ) as List;
附上更新场景的答案-
DECLARE @T TABLE
(
[Col1] VARCHAR(20)
, [RowNum] INT
) ;
INSERT INTO @T
VALUES
( N'second', 1 )
, ( N'fifth', 4 )
, ( N'fourth', 3 )
--, ( N'zzz', 1 )
, ( N'third', 2 )
---- OR when "zzz" is part of this list
--VALUES
-- ( N'second', 2 )
-- , ( N'fifth', 5 )
-- , ( N'fourth', 4 )
-- , ( N'zzz', 1 )
-- , ( N'third', 3 )
SELECT STUFF ((
SELECT ',' + [SQ].[Col1]
FROM
(
SELECT N'zzz' AS [Col1]
, 0 AS [RowNum]
UNION
SELECT [Col1]
, [RowNum]
FROM @T
) AS [SQ]
ORDER BY [RowNum]
FOR XML PATH ( '' ), TYPE
).[value] ( '.', 'varchar(MAX)' ), 1, 1, ''
) ;
Returns
zzz,第二,第三,第四,第五
Code/data:
DECLARE @T TABLE
(
[Col1] VARCHAR(20)
, [RowNum] INT
) ;
INSERT INTO @T
VALUES
( N'second', 1 )
, ( N'fifth', 4 )
, ( N'fourth', 3 )
--, ( N'zzz', 1 )
, ( N'third', 2 )
---- OR when "zzz" is part of this list
--VALUES
-- ( N'second', 2 )
-- , ( N'fifth', 5 )
-- , ( N'fourth', 4 )
-- , ( N'zzz', 1 )
-- , ( N'third', 3 )
SELECT STUFF ((
SELECT ',' + [SQ].[Col1]
FROM
(
SELECT N'zzz' AS [Col1]
, 1 AS [RowNum]
UNION
SELECT [Col1]
, [RowNum]
FROM @T
) AS [SQ]
FOR XML PATH ( '' ), TYPE
).[value] ( '.', 'varchar(MAX)' ), 1, 1, ''
) ;
当前输出:
fifth,fourth,second,third,zzz
目标: 如果在联合的第二部分中缺失,则在输出字符串中添加 "zzz," 并且这些值应根据联合第二部分中定义的 [rownum] 字段中指定的值按 ASC 顺序排列。如果 "zzz" 已经存在于输入的第二部分(在这种情况下它将始终为 RowNum 1),它应该 return 它只作为第一个值出现一次。
预期输出:
zzz,second,third,fourth,fifth
由于我在创建此 post 时出错,更新了要求。更新 code/data 表示更准确的场景。请注意 UNION 第二部分的 RowNum seq,它也是从 1 开始的,但是这次,它可能与 "zzz" 相关联,也可能不相关联。基本上,我想在前面加上 "zzz" 在逗号分隔和有序输出中(如果不存在)。
希望以下内容对您有所帮助。
SELECT ',' + [SQ].[Col1]
FROM
(
SELECT N'first' AS [Col1],1 AS [RowNum]
UNION
SELECT [ABC].[Col1],[ABC].[RowNum]
FROM
(
VALUES
( N'second', 2 )
, ( N'fifth', 5 )
, ( N'fourth', 4 )
--, ( N'first', 1 )
, ( N'third', 3 )
) AS [ABC] ( [Col1], [RowNum] )
) AS [SQ]
ORDER BY [RowNum]
FOR XML PATH ( '' ), TYPE
).[value] ( '.', 'varchar(MAX)' ), 1, 1, ''
) ;
Returns一个输出
第一,第二,第三,第四,第五
常用 Table 表达式 (CTE) 提供了一种将查询分解为更简单步骤的简便方法。请注意,您可以通过切换出最后的select
语句来查看每一步的结果。
with
Assortment as (
-- Start with the "input" rows.
select Col1, RowNum
from ( values ( N'second', 2 ), ( N'fifth', 5 ), ( N'fourth', 4 ),
-- ( N'first', 1 ),
( N'third', 3 ) ) ABC ( Col1, RowNum ) ),
ExtendedAssortment as (
-- Conditionally add "first".
select Col1, RowNum
from Assortment
union all -- Do not remove duplicate rows.
select N'first', 1
where not exists ( select 42 from Assortment where Col1 = N'first' ) )
-- Output the result.
-- Intermediate results may be seen by uncommenting one of the alternate select statements.
-- select * from Assortment;
-- select * from ExtendedAssortment;
select Stuff(
( select N',' + Col1 from ExtendedAssortment order by RowNum for XML path(N''), type).value( N'.[1]', 'NVarChar(max)' ),
1, 1, N'' ) as List;
可以使用输入表执行相同的逻辑:
-- Rows to be included in the comma delimited string.
declare @Input as Table ( Col1 NVarChar(20), RowNum Int );
insert into @Input ( Col1, RowNum ) values
( N'second', 2 ), ( N'fifth', 5 ),
--( N'ZZZ', 17 ), -- Test row.
( N'fourth', 4 ), ( N'third', 3 );
select * from @Input;
-- Mandatory value that must appear in the result. One row only.
declare @Mandatory as Table ( Col1 NVarChar(20), RowNum Int );
-- By using the maximum negative value for an Int this value will be prepended
-- (unless other rows happen to have the same RowNum value).
insert into @Mandatory ( Col1, RowNum ) values ( N'ZZZ', -2147483648 );
select * from @Mandatory;
-- Process the data.
with
AllRows as (
select Col1, RowNum
from @Input
union all
select Col1, RowNum
from @Mandatory
where not exists ( select 42 from @Mandatory as M inner join @Input as I on M.Col1 = I.Col1 ) )
-- Output the result.
-- Intermediate results may be seen by uncommenting the alternate select statement.
--select * from AllRows;
select Stuff(
( select N',' + Col1 from AllRows order by RowNum for XML path(N''), type).value( N'.[1]', 'NVarChar(max)' ),
1, 1, N'' ) as List;
附上更新场景的答案-
DECLARE @T TABLE
(
[Col1] VARCHAR(20)
, [RowNum] INT
) ;
INSERT INTO @T
VALUES
( N'second', 1 )
, ( N'fifth', 4 )
, ( N'fourth', 3 )
--, ( N'zzz', 1 )
, ( N'third', 2 )
---- OR when "zzz" is part of this list
--VALUES
-- ( N'second', 2 )
-- , ( N'fifth', 5 )
-- , ( N'fourth', 4 )
-- , ( N'zzz', 1 )
-- , ( N'third', 3 )
SELECT STUFF ((
SELECT ',' + [SQ].[Col1]
FROM
(
SELECT N'zzz' AS [Col1]
, 0 AS [RowNum]
UNION
SELECT [Col1]
, [RowNum]
FROM @T
) AS [SQ]
ORDER BY [RowNum]
FOR XML PATH ( '' ), TYPE
).[value] ( '.', 'varchar(MAX)' ), 1, 1, ''
) ;
Returns
zzz,第二,第三,第四,第五