복붙노트

[SQL] 사용자 정의 집계 함수 (CONCAT) SQL Server의

SQL

사용자 정의 집계 함수 (CONCAT) SQL Server의

질문 : 사용자 정의 집계 함수를 작성하려면 그룹화에 서로 연결하여 문자열이.

그래서 나는 할 수 있다고

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

모든 I의 발견은 SQL CLR 집계 함수,하지만 난 CLR하지 않고, SQL이 필요합니다.

편집 : 1 쿼리는 다음과 같이한다 :

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

편집 2 : CLR없이 불가능하다는 사실이다. 그렇지 않은 XML 인코딩 된 특수 문자를 않도록 그러나 astander에 의해 부속 선택의 대답은 수정 될 수 있습니다.

이에 대한 미묘한 변화는 "XML 경로에 대해"후에이를 추가하는 것입니다 : ,

 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   

해결법

  1. ==============================

    1.당신은 CLR의 외부 쓰기 사용자 정의 집계 할 수 없습니다.

    당신은 CLR의 외부 쓰기 사용자 정의 집계 할 수 없습니다.

    당신이 순수 T-SQL에서 쓸 수있는 함수의 유일한 유형은 스칼라 및 테이블 반환 함수입니다.

    이는 쇼 T-SQL 및 CLR 옵션 기능을 CREATE 함께하는 목록 만 CLR 스타일 옵션을 AGGREGATE를 생성하기위한 페이지를, 비교.

  2. ==============================

    2.같은에서보세요. 이 집계 함수가 아닙니다. 당신이 당신의 자신의 집계 함수를 구현하고자하는 경우에는 CLR해야 할 것이다 ...

    같은에서보세요. 이 집계 함수가 아닙니다. 당신이 당신의 자신의 집계 함수를 구현하고자하는 경우에는 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
    
  3. ==============================

    3.2017에서 시작이 내장되어 CONCATENATE 집계 함수 STRING_AGG :)

    2017에서 시작이 내장되어 CONCATENATE 집계 함수 STRING_AGG :)

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

  4. ==============================

    4.같은 방법을 다룹 연결 주변이 링크 발견

    같은 방법을 다룹 연결 주변이 링크 발견

    항목의 수를 알 수없는 경우 값을 연결

    비 신뢰할 수있는 방법

    이 집계 함수를 포함하지 않지만 문제와 함께 당신을 도울 수있는가에 연결 주위에 약간의 사용이있을 수 있습니다.

  5. ==============================

    5.이 솔루션은 비주얼 스튜디오에서 배포의 필요없이 또는 서버에 DLL 파일과 함께 작동합니다.

    이 솔루션은 비주얼 스튜디오에서 배포의 필요없이 또는 서버에 DLL 파일과 함께 작동합니다.

    복사 - 붙여 넣기 그리고 작업!

    http://groupconcat.codeplex.com/

    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 )
    
  6. ==============================

    6.당신은 내가 순수 T-SQL에서 사용자 지정 집계 연결 기능을 만들려면 아래 한 일을 같이 할 수 있습니다. 분명히 나는 ​​열을 기준으로 하드 코딩 테이블 이름과 그룹 갔다하지만 접근 방식을 설명한다. 이 입력 매개 변수로 구성 동적 TSQL을 사용하여 진정한 일반적인 함수를 만들 수있는 방법은 아마이있다.

    당신은 내가 순수 T-SQL에서 사용자 지정 집계 연결 기능을 만들려면 아래 한 일을 같이 할 수 있습니다. 분명히 나는 ​​열을 기준으로 하드 코딩 테이블 이름과 그룹 갔다하지만 접근 방식을 설명한다. 이 입력 매개 변수로 구성 동적 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 
    
  7. from https://stackoverflow.com/questions/4374709/custom-aggregate-function-concat-in-sql-server by cc-by-sa and MIT license