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,第二,第三,第四,第五