17

SQL Server でMySQL のCONCAT_WS()関数をエミュレートするにはどうすればよいですか?

CONCAT()この関数は、SQL Server 2012 の関数と似ていますが、NULL 以外の項目間に区切り記号を追加する点が異なります。

SELECT id, CONCAT_WS('; ', a, b, c, d) AS bar
FROM foo
ORDER BY id;
| ID | BAR        |
|----|------------|
|  1 | a; b; c; d |
|  2 | b; d       |
|  3 | a; d       |
|  4 |            |

( MySQLフィドル)

4

6 に答える 6

21

いくつかのトリックを使用できます。

彼は実例です:

CREATE TABLE foo (
  id INT IDENTITY(1, 1) NOT NULL,
  a VARCHAR(50),
  b VARCHAR(50),
  c VARCHAR(50),
  d VARCHAR(50),
  PRIMARY KEY (id)
);

INSERT INTO foo (a, b, c, d) VALUES ('a', 'b', 'c', 'd');
INSERT INTO foo (a, b, c, d) VALUES (NULL, 'b', NULL, 'd');
INSERT INTO foo (a, b, c, d) VALUES ('a', NULL, NULL, 'd');
INSERT INTO foo (a, b, c, d) VALUES (NULL, NULL, NULL, NULL);
SELECT id,
STUFF(
    COALESCE('; ' + a, '') +
    COALESCE('; ' + b, '') +
    COALESCE('; ' + c, '') +
    COALESCE('; ' + d, ''),
1, 2, '') AS bar
FROM foo
ORDER BY id
| ID | BAR        |
|----|------------|
|  1 | a; b; c; d |
|  2 | b; d       |
|  3 | a; d       |
|  4 | (null)     |

の目的はSTUFF(..., 1, 2, '')、最初のセパレーターを削除することです (2は、この場合のセパレーターの長さです)。

これは、SQL Server 2005 (およびおそらくそれ以前のバージョン) で動作するはずです。

注: オリジナルとは異なりCONCAT_WS()、私たちのバージョンはNULLすべてのアイテムが の場合に戻りますNULL。正直なところ、それはより良い選択だと思いますが、とにかく簡単に変更できるはずです.

于 2013-10-17T16:33:38.963 に答える
8

別のアプローチは、次のようなFOR XML サブクエリを使用することです。

SELECT
  id,
  bar = STUFF(
    (
      SELECT '; ' + v
      FROM (VALUES (a), (b), (c), (d)) AS v (v)
      FOR XML PATH (''), TYPE
    ).value('.[1]', 'varchar(max)'),
    1, 2, ''
  )
FROM foo
ORDER BY id;

一方では、これは確かに一連の COALESCE 呼び出しよりも複雑に見えます。一方、これは区切り文字が 1 回だけ指定されているという点でプロトタイプに近いです。

使用される構文には、少なくとも SQL Server 2008+ が必要ですが、VALUES コンストラクターが次のように変更された場合

SELECT a UNION ALL
SELECT b UNION ALL
SELECT c UNION ALL
SELECT d

クエリは SQL Server 2005 でも実行されます。

于 2013-10-17T16:50:23.533 に答える
6

SQL Server 2017以降で は、ビルトインを使用できますCONCAT_WS

CONCAT_WS

第 1 引数に指定された区切り文字を使用して、可変数の引数を連結します。(CONCAT_WS は区切り記号付きの連結を示します。)

CONCAT_WS ( separator, argument1, argument1 [, argumentN]… ) 

NULL 値の扱い

CONCAT_WS は、SET CONCAT_NULL_YIELDS_NULL {ON|OFF} 設定を無視します。

すべての引数が null の場合、varchar(1) 型の空の文字列が返されます。

連結時に null 値は無視され、区切り記号は追加されません。これにより、2 番目のアドレス フィールドなど、空白の値を持つことが多い文字列を連結するという一般的なシナリオが容易になります。例 B を参照してください。

シナリオで区切り文字に null 値を含める必要がある場合は、ISNULL 関数を使用した例 C を参照してください。

したがって、最初のクエリを使用できます。

SELECT id, CONCAT_WS('; ', a, b, c, d) AS bar
FROM foo
ORDER BY id;

デシベル<>フィドルのデモ

于 2016-12-28T16:10:01.327 に答える
0

FOR XML PATHでそれを行います。
VALUES の代わりに共用体 (UNION ALL) を使用できます。これには、SQL-Server 2005 で引き続き機能するという付加価値があり (当社ではまだサポートする必要があります)、NULL 値を削除できます。

DECLARE @in_SearchTerm1 nvarchar(100) 
DECLARE @in_SearchTerm2 nvarchar(100) 
DECLARE @in_SearchTerm3 nvarchar(100) 
DECLARE @in_SearchTerm4 nvarchar(100) 

SET @in_SearchTerm1 = N'a'
SET @in_SearchTerm2 = N''
SET @in_SearchTerm3 = N'c'
SET @in_SearchTerm4 = N''

SELECT 
    COALESCE
    (
        STUFF
        (
            (
                SELECT ' / ' + RPT_SearchTerm AS [text()]
                FROM 
                (
                                  SELECT NULLIF(@in_SearchTerm1, N'') AS RPT_SearchTerm, 1 AS RPT_Sort 
                        UNION ALL SELECT NULLIF(@in_SearchTerm2, N'') AS RPT_SearchTerm, 2 AS RPT_Sort  
                        UNION ALL SELECT NULLIF(@in_SearchTerm3, N'') AS RPT_SearchTerm, 3 AS RPT_Sort 
                        UNION ALL SELECT NULLIF(@in_SearchTerm4, N'') AS RPT_SearchTerm, 4 AS RPT_Sort 
                ) AS tempT 
                WHERE RPT_SearchTerm IS NOT NULL 
                ORDER BY RPT_Sort 
                FOR XML PATH(N''), TYPE 
            ).value('.', 'nvarchar(MAX)') 
            ,1
            ,3
            ,N''
        )
        ,N''
    ) AS RPT_SearchTerms 

nvarchar の使用に注意してください - すでに varchar の使用をやめてください。
また、順序を維持するために、注文する必要があります。


それで、これは何をしますか:

目標:
レポートの 4 つの個別のフィルターに入力された 4 つの検索語を取得します。
これらの 4 つの検索用語を で連結してレポートに表示し' / 'ます。検索語が空
の場合はありません。 これは、term4/term2/term3/term1 などではなく、term1/term2/term3/term4 のように順番に表示する必要があります。' / / '

方法:
4 つの検索用語を結合して、順序を保持するための並べ替え値を追加します。

和集合から検索語とセパレーターを選択します (separatur + null = null)

SELECT ' / ' + RPT_SearchTerm 
FROM (UNION OF SEARCH TEMRS) AS tempT

RPT_Sort で並べ替える

ここで、tempT のすべての値 (区切り文字 + テキスト) を 1 つの XML ファイル ( FOR XML) に選択します。ここで、すべての値は空のタグ名を持つ XML 要素( ) でPATH(N'')あり、値 XML テキスト ( AS [text()]) (別名 element.innerXML) を選択します。

その結果を XML 要素 ( TYPE) として取得し、その XML 要素 ( ) の innerText 文字列を取得します.value('.', 'nvarchar(MAX)')(別名 XML デコード)。

最後に、先頭の「/」( STUFF(var, 1,3, N''))を削除します。

これは原理的には

CONCAT_WS(' / ', @in_SearchTerm1, @in_SearchTerm2, @in_SearchTerm3, @in_SearchTerm4)

nullif を追加します。

CONCAT_WS(' / ', NULLIF(@in_SearchTerm1, '') , NULLIF(@in_SearchTerm2, ''), NULLIF(@in_SearchTerm3, ''), NULLIF(@in_SearchTerm4, ''))

そしてあなたはそこにいます。

これは、SQL-ServerでCONCAT_WSを引き続き実行できる方法です...

于 2016-09-14T08:05:09.227 に答える
0

これは古い投稿であることは知っていますが、同じ問題が発生します。

これには CONCAT() 関数を使用するだけです。

個々のフィールドに保存された住所行があり、すべての行を結合して住所を作成したいと考えていました。

CONCAT() 関数が NULL を処理でき、それを空の文字列に置き換えることがわかりました。また、何かプラス NULL が NULL の場合。

したがって、通常の CONCAT() 関数を使用し、各住所行の末尾にスペースを追加して、その行が NULL の場合、結合出力は null になります

SELECT 
    CONCAT(Address01 + ' ', Address02 + ' ', Address03 + ' ', Address04) AS Address 
FROM myTable
于 2017-08-20T03:12:33.453 に答える