문제

내가 원하는 행을 반환하는 쿼리가 있습니다.

QuestionID  QuestionTitle  UpVotes  DownVotes  
==========  =============  =======  =========  
2142075     Win32: Cre...        0          0  
2232727     Win32: How...        2          0  
1870139     Wondows Ae...       12          0  

이제 나는 가고 싶다 반품, 쉼표 분리 된 목록이 포함되어 있습니다.저자"(예 : 원래 포스터 및 편집자). 예 :

QuestionID  QuestionTitle  UpVotes  DownVotes  Authors
==========  =============  =======  =========  ==========
2142075     Win32: Cre...        0          0  Ian Boyd  
2232727     Win32: How...        2          0  Ian Boyd, roygbiv
1870139     Wondows Ae...       12          0  Ian Boyd, Aaron Klotz, Jason Diller, danbystrom


가짜

SQL Server 2000에는 a가 없습니다 CONCAT(AuthorName, ', ') 집계 작업, 나는 그것을 속이고 있습니다 - 간단한 하위 선택을 수행합니다. TOP 1 저자와 저자 수.

QuestionID  QuestionTitle  UpVotes  DownVotes  FirstAuthor  AuthorCount  
==========  =============  =======  =========  ===========  =========== 
2142075     Win32: Cre...        0          0  Ian Boyd               1 
2232727     Win32: How...        2          0  Ian Boyd               2
1870139     Wondows Ae...       12          0  Ian Boyd               3

저자가 둘 이상인 경우 사용자에게 타원 ( "…")을 보여주고 둘 이상이 있음을 나타냅니다. 예 : 사용자는 다음을 볼 수 있습니다.

QuestionID  QuestionTitle  UpVotes  DownVotes  Authors
==========  =============  =======  =========  ==========
2142075     Win32: Cre...        0          0  Ian Boyd
2232727     Win32: How...        2          0  Ian Boyd, …
1870139     Wondows Ae...       12          0  Ian Boyd, …

그리고 그것은 일반적으로 a 의문 편집되지 않음 - 99% 케이스를 완벽하게 지원하고 1% 케이스는 절반에 불과합니다.-입증 또한.


나사산 재구성

더 복잡하고 버그가 발생한 솔루션으로, 나는 표시된 목록을 반복하고 각각의 스레드-풀 작업자 스레드를 회전시키는 것을 생각하고있었습니다. "의문"목록에서 데이터베이스에 대한 쿼리를 수행하여 저자 목록을 가져온 다음 메모리에서 목록을 집계합니다. 이는 목록이 (기본) 응용 프로그램에서 먼저 채워진다는 것을 의미합니다. 그런 다음 나중에 수천 개의 개별 쿼리를 발행합니다.

그러나 그것은 끔찍하고 끔찍하게, 끔찍한, 느리게 될 것입니다. 스레드 작업이기 때문에 버그가 달린 것은 말할 것도 없습니다.


그래 그래 그래

아담 정비사 꽤 분명하게 말합니다:

SQL Server에서 행을 구분 된 문자열로 연결하지 마십시오. 클라이언트 측을 수행하십시오.

방법을 말해 주시면 할게요.


/울다

누구든지 더 나은 솔루션을 생각할 수 있습니다. 즉, 원래 "Top 1 Plus Ellipses"솔루션보다 빠른 (한 순서 내에서)

예를 들어, REACH ROW가 관련 결과 세트가있는 결과 세트를 반환하는 방법이 있습니까? 따라서 각 "마스터"행에 대해 목록이 포함 된 "세부 사항"결과 세트를 얻을 수 있습니다.


베스트 답변을위한 코드

케이드 다음으로 연결 Adam Machanic의 해결책 나는 최고를 좋아한다. 마술을 통해 작동하는 것으로 보이는 사용자 정의 기능 :

CREATE FUNCTION dbo.ConcatAuthors(@QuestionID int)
RETURNS VARCHAR(8000)
AS
BEGIN
    DECLARE @Output VARCHAR(8000)
    SET @Output = ''

    SELECT @Output =    CASE @Output 
                WHEN '' THEN AuthorName 
                ELSE @Output + ', ' + AuthorName 
                END
    FROM  (
        SELECT QuestionID, AuthorName, QuestionDate AS AuthorDate FROM Questions
        UNION
        SELECT QuestionID, EditorName, EditDate FROM QuestionEdits
    ) dt
    WHERE dt.QuestionID = @QuestionID
    ORDER BY AuthorDate

    RETURN @Output
END

T-SQL 사용

SELECT QuestionID, QuestionTitle, UpVotes, DownVotes, dbo.ConcatAuthors(AuthorID)
FROM Questions
도움이 되었습니까?

해결책

이 기사를 살펴보십시오.

http://dataeducation.com/rowset-string-concatenation-hit-method-is-best/

http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/ (SQL Server 2000에서 작동하는 응답의 Phil Factor의 크로스 조인 솔루션 참조)

분명히 SQL Server 2005에서 For XML 트릭은 가장 쉽고 가장 유연하며 일반적으로 가장 성능이 뛰어납니다.

각 행에 대한 행을 반환하는 한, 어떤 이유로 든 여전히 그렇게하려면 저장된 절차에서 그렇게 할 수 있지만 클라이언트는 첫 번째 행에 모든 행을 소비 한 다음 다음로 이동해야합니다. 행 세트 및 첫 번째 행 세트 등의 첫 번째 행과 연결하십시오. SP는 첫 번째 행 세트로 반환 한 것과 동일한 세트에서 커서를 열고 모든 하위 로우 세트를 생성하기 위해 여러 선택을 순서대로 실행해야합니다. 내가 한 기술이지만 어디에서 모두 실제로 데이터가 필요했습니다 (예 : 완전히 인구가 많은 트리 뷰에서).

그리고 사람들이 말하는 것에 관계없이, 클라이언트 측을하는 것은 종종 대역폭의 매우 큰 낭비입니다. 모든 행을 반환하고 클라이언트 측에서 루핑을 반환하고 깨지는 것은 수많은 수많은 열이 시작될 때 수많은 열이 전송되고 있음을 의미합니다. 행 끝에서 변경 열을 얻기 위해 각 행.

당신이 어디에 있든, 그것은 여야합니다 알려진 결정 기반 당신의 유스 케이스.

다른 팁

이 솔루션에 대한 3 가지 접근 방식, 여기에 게시 된 ActiveX 스크립팅 및 UDF 기능을 시도했습니다.

저에게 가장 효과적인 스크립트 (속도 별)는 여러 쿼리를 실행하여 AdditioAnl 데이터를 연결하는 Bizzarely Axtive-X 스크립트였습니다.

UDF는 변환하는 데 평균 22 분이 걸렸으며, 서브 쿼리 방법 (여기에 게시)은 약 5m를 가져 갔고 ActiveX 스크립트는 4M30을 차지했습니다. 이것은 내가 도랑하고자하는 스크립트이기 때문에 내 성가심에 많이 걸렸습니다. 다른 곳에서 몇 가지 더 많은 효율성을 다룰 수 있는지 알아야합니다.

내 스크립트에 주문이 필요하기 때문에 TEMPDB가 데이터를 저장하는 데 사용되는 TEMPDB가 추가 30을 사용한다고 생각합니다.

나는 엄청난 양의 텍스트 데이터를 동의하고 있음에 주목해야합니다.

당신은 또한 이것을 살펴볼 수 있습니다 스크립트. 기본적으로 Cade Roux가 그의 게시물에서 언급 한 크로스 조인 접근법입니다.

위의 접근 방식은 매우 깨끗해 보입니다. 먼저보기를 수행하고 두 번째로보기의 값을 기반으로 문을 만들어야합니다. 두 번째 SQL 문은 코드에서 동적으로 빌드 할 수 있으므로 간단하게 사용해야합니다.

이것이 SQL Server 2000에서 작동하는지 확실하지 않지만 시도해 볼 수 있습니다.

--combine parent and child, children are CSV onto parent row
CREATE TABLE #TableA (RowID int, Value1 varchar(5), Value2 varchar(5))
INSERT INTO #TableA VALUES (1,'aaaaa','A')
INSERT INTO #TableA VALUES (2,'bbbbb','B')
INSERT INTO #TableA VALUES (3,'ccccc','C')

CREATE TABLE #TableB (RowID int, TypeOf varchar(10))
INSERT INTO #TableB VALUES (1,'wood')
INSERT INTO #TableB VALUES (2,'wood')
INSERT INTO #TableB VALUES (2,'steel')
INSERT INTO #TableB VALUES (2,'rock')
INSERT INTO #TableB VALUES (3,'plastic')
INSERT INTO #TableB VALUES (3,'paper')


SELECT
    a.*,dt.CombinedValue
    FROM #TableA        a
        LEFT OUTER JOIN (SELECT
                             c1.RowID
                                 ,STUFF(
                                          (SELECT
                                               ', ' + TypeOf
                                               FROM (SELECT
                                                         a.RowID,a.Value1,a.Value2,b.TypeOf
                                                         FROM #TableA                 a
                                                             LEFT OUTER JOIN #TableB  b ON a.RowID=b.RowID
                                                    ) c2
                                               WHERE c2.rowid=c1.rowid
                                               ORDER BY c1.RowID, TypeOf
                                               FOR XML PATH('') 
                                          )
                                          ,1,2, ''
                                       ) AS CombinedValue
                             FROM (SELECT
                                       a.RowID,a.Value1,a.Value2,b.TypeOf
                                       FROM #TableA                 a
                                           LEFT OUTER JOIN #TableB  b ON a.RowID=b.RowID
                                  ) c1
                             GROUP BY RowID
                        ) dt ON a.RowID=dt.RowID

SQL Server 2005의 출력 :

RowID       Value1 Value2 CombinedValue
----------- ------ ------ ------------------
1           aaaaa  A      wood
2           bbbbb  B      rock, steel, wood
3           ccccc  C      paper, plastic

(3 row(s) affected)

편집하다 XML 경로를 XML RAW로 대체하는 쿼리이므로 SQL Server 2000에서 작동해야합니다.

SELECT
    a.*,dt.CombinedValue
    FROM #TableA        a
        LEFT OUTER JOIN (SELECT
                             c1.RowID
                                 ,STUFF(REPLACE(REPLACE(
                                          (SELECT 
                                               ', ' + TypeOf as value
                                               FROM (SELECT
                                                         a.RowID,a.Value1,a.Value2,b.TypeOf
                                                         FROM #TableA                 a
                                                             LEFT OUTER JOIN #TableB  b ON a.RowID=b.RowID
                                                    ) c2
                                               WHERE c2.rowid=c1.rowid
                                               ORDER BY c1.RowID, TypeOf
                                               FOR XML RAW
                                          )
                                         ,'<row value="',''),'"/>','')
                                   , 1, 2, '') AS CombinedValue
                             FROM (SELECT
                                       a.RowID,a.Value1,a.Value2,b.TypeOf
                                       FROM #TableA                 a
                                           LEFT OUTER JOIN #TableB  b ON a.RowID=b.RowID
                                  ) c1
                             GROUP BY RowID
                        ) dt ON a.RowID=dt.RowID

원래 쿼리와 동일한 출력

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top