28

質問:groupbyの文字列を連結するカスタム集計関数を作成したいと思います。

私ができるように

SELECT SUM(FIELD1) as f1, MYCONCAT(FIELD2)  as f2
FROM TABLE_XY
GROUP BY FIELD1, FIELD2

私が見つけたのはSQLCRL集計関数だけですが、CLRなしのSQLが必要です。



編集:1
クエリは次のようになります。

   SELECT SUM(FIELD1) as f1, MYCONCAT(FIELD2)  as f2
    FROM TABLE_XY
    GROUP BY FIELD0



編集2:
それはCLRなしでは不可能であることは事実です。
ただし、スタンダーによる副選択回答は、特殊文字をXMLエンコードしないように変更できます。

これに対する微妙な変更は、「FORXMLPATH」の後にこれを追加することです。

 TYPE 
                  ).value('.[1]', 'nvarchar(MAX)') 

ここにいくつかの例があります

DECLARE @tT table([A] varchar(200), [B] varchar(200));

INSERT INTO @tT VALUES ('T_A', 'C_A');
INSERT INTO @tT VALUES ('T_A', 'C_B');
INSERT INTO @tT VALUES ('T_B', 'C_A');
INSERT INTO @tT VALUES ('T_C', 'C_A');
INSERT INTO @tT VALUES ('T_C', 'C_B');
INSERT INTO @tT VALUES ('T_C', 'C_C');

SELECT 
      A AS [A]
      ,
      ( 
            STUFF 
            ( 
                    ( 
                             SELECT DISTINCT 
                                   ', ' + tempT.B AS wtf 
                             FROM @tT AS tempT 
                             WHERE (1=1) 
                             --AND tempT.TT_Status = 1 
                             AND tempT.A = myT.A 
                             ORDER BY wtf 
                             FOR XML PATH, TYPE 
                    ).value('.[1]', 'nvarchar(MAX)') 
                    , 1, 2, '' 
            ) 
      ) AS [B] 
FROM @tT AS myT
GROUP BY A 





SELECT 
      ( 
            SELECT 
                  ',äöü<>' + RM_NR AS [text()] 
            FROM T_Room 
            WHERE RM_Status = 1 
            ORDER BY RM_NR 
            FOR XML PATH('') 

      ) AS XmlEncodedNoNothing  


      ,
      SUBSTRING
      (
            (
                  SELECT 
                        ',äöü<>' + RM_NR  AS [data()] 
                  FROM T_Room 
                  WHERE RM_Status = 1 
                  ORDER BY RM_NR 
                  FOR XML PATH('')
            )
            ,2
            ,10000
      ) AS XmlEncodedSubstring  


      ,
      ( 
            STUFF 
            ( 
                  ( 
                        SELECT ',äöü<>' + RM_NR + CHAR(10) 
                        FROM T_Room 
                        WHERE RM_Status = 1 
                        ORDER BY RM_NR 
                        FOR XML PATH, TYPE 
                  ).value('.[1]', 'nvarchar(MAX)') 
                  , 1, 1, '' 
            ) 
      ) AS XmlDecodedStuffInsteadSubstring   
4

6 に答える 6

16

CLRの外部でカスタム集計を作成することはできません。

純粋なT-SQLで記述できる関数のタイプは、スカラー関数とテーブル値関数のみです。

CLRスタイルのオプションのみを一覧表示するCREATEAGGREGATEのページと、T-SQLおよびCLRオプションを表示するCREATEFUNCTIONのページを比較します。

于 2010-12-07T08:35:47.093 に答える
14

のようなものを見てください。これは集計関数ではありません。独自の集計関数を実装する場合は、CLRである必要があります...

DECLARE @Table TABLE(
        ID INT,
        Val VARCHAR(50)
)
INSERT INTO @Table (ID,Val) SELECT 1, 'A'
INSERT INTO @Table (ID,Val) SELECT 1, 'B'
INSERT INTO @Table (ID,Val) SELECT 1, 'C'
INSERT INTO @Table (ID,Val) SELECT 2, 'B'
INSERT INTO @Table (ID,Val) SELECT 2, 'C'

--Concat
SELECT  t.ID,
        SUM(t.ID),
        stuff(
                (
                    select  ',' + t1.Val
                    from    @Table t1
                    where   t1.ID = t.ID
                    order by t1.Val
                    for xml path('')
                ),1,1,'') Concats
FROM    @Table t
GROUP BY t.ID
于 2010-12-07T08:36:11.173 に答える
11

2017年以降、組み込みの連結集計関数STRING_AGGがあります:)

https://docs.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-2017

于 2018-06-06T15:03:44.853 に答える
4

次のようなメソッドをカバーする連結に関するこのリンクを見つけました

アイテムの数がわからない場合の値の連結

  • 再帰CTEメソッド
  • ブラックボックスXMLメソッド
  • 共通言語ランタイムの使用
  • 再帰を伴うスカラーUDF
  • WHILEループを使用したテーブル値UDF
  • 動的SQL
  • カーソルアプローチ

信頼できないアプローチ

  • t-SQL更新拡張機能を備えたスカラーUDF
  • SELECTで変数を連結したスカラーUDF

誇張された関数については説明していませんが、問題を解決するために連結を使用する場合があります。

于 2010-12-07T08:40:10.037 に答える
4

このソリューションは、VisualStudioまたはサーバーのdllファイルから展開する必要なしに機能します。

コピー&ペーストして機能します!

https://github.com/orlando-colamatteo/ms-sql-server-group-concat-sqlclr

dbo.GROUP_CONCAT(VALUE )
dbo.GROUP_CONCAT_D(VALUE ), DELIMITER )  
dbo.GROUP_CONCAT_DS(VALUE , DELIMITER , SORT_ORDER )
dbo.GROUP_CONCAT_S(VALUE , SORT_ORDER )
于 2015-11-10T15:39:23.790 に答える
0

以下で行ったようなことを実行して、純粋なT-SQLでカスタムの集計連結関数を作成できます。明らかに、ハードコードされたテーブル名とgroup by列を使用しましたが、アプローチを説明する必要があります。入力パラメータから構築された動的TSQLを使用して、これを真にジェネリックな関数にする方法はおそらくいくつかあります。

/*
User defined function to help perform concatenations as an aggregate function
Based on AdventureWorks2008R2 SalesOrderDetail table
*/

--select * from sales.SalesOrderDetail 

IF EXISTS (SELECT * 
        FROM   sysobjects 
        WHERE  name = N'fnConcatenate')
    DROP FUNCTION fnConcatenate
GO

CREATE FUNCTION fnConcatenate
 (
      @GroupByValue int
        )                       
returnS varchar(8000)
as

BEGIN


    DECLARE @SqlString varchar(8000)
    Declare @TempStore varchar(25)
    select @SqlString =''

    Declare @MyCursor as Cursor
          SET @MyCursor = CURSOR FAST_FORWARD 
          FOR 
          Select ProductID 
          From sales.SalesOrderDetail  where SalesOrderID  = @GroupByValue
          order by SalesOrderDetailID asc


      OPEN @MyCursor 

         FETCH NEXT FROM @MyCursor
         INTO @TempStore

        WHILE @@FETCH_STATUS = 0 
        BEGIN 


          select @SqlString = ltrim(rtrim(@TempStore )) +',' + ltrim(rtrim(@SqlString))
          FETCH NEXT FROM @MyCursor INTO @TempStore

        END 

CLOSE @MyCursor
DEALLOCATE @MyCursor

RETURN @SqlString

END
GO


select  SalesOrderID, Sum(OrderQty),  COUNT(*) as DetailCount , dbo.fnConcatenate(salesOrderID) as ConCatenatedProductList
from sales.SalesOrderDetail 
where salesOrderID= 56805 
group by SalesOrderID 
于 2013-06-11T20:49:42.020 に答える