CTE chỉ là một mối quan hệ được tạo tạm thời (các bảng và khung nhìn là cả hai quan hệ) chỉ tồn tại cho "cuộc sống" của truy vấn hiện tại.
Tôi đã chơi với tên CTE và tên trường. Tôi thực sự không thích sử dụng lại các tên trường như id ở nhiều nơi; Tôi có xu hướng nghĩ rằng những người khó hiểu. Và vì chỉ sử dụng cho tên.id là ORDER BY trong câu lệnh ROW_NUMBER() đầu tiên, tôi không sử dụng lại nó trong tương lai.
WITH namesNumbered as (
select myId, Name,
ROW_NUMBER() OVER (
PARTITION BY myId
ORDER BY id
) as nameNum
FROM names
)
, namesJoined(myId, Name, nameCount) as (
SELECT myId,
Cast(Name AS VARCHAR(225)),
1
FROM namesNumbered nn1
WHERE nameNum = 1
UNION ALL
SELECT nn2.myId,
Cast(
Rtrim(nc.Name) + ',' + nn2.Name
AS VARCHAR(225)
),
nn.nameNum
FROM namesJoined nj
INNER JOIN namesNumbered nn2 ON nn2.myId = nj.myId
and nn2.nameNum = nj.nameCount + 1
)
SELECT myId, Name
FROM (
SELECT myID, Name,
ROW_NUMBER() OVER (
PARTITION BY myId
ORDER BY nameCount DESC
) AS finalSort
FROM namesJoined
) AS tmp
WHERE finalSort = 1
Các CTE đầu tiên, namesNumbered, trả về hai lĩnh vực chúng ta quan tâm và một giá trị sắp xếp; chúng tôi không thể chỉ sử dụng tên.id cho điều này vì chúng tôi cần, cho mỗi giá trị myId, để có giá trị 1, 2, .... tên.id sẽ có 1, 2 ... cho myId = 1 nhưng nó sẽ có giá trị bắt đầu cao hơn cho các giá trị myId tiếp theo.
CTE thứ hai, tên Đã đặt trước, phải có tên trường được chỉ định trong chữ ký CTE vì nó sẽ được đệ quy. Trường hợp cơ sở (một phần trước UNION ALL) cung cấp cho chúng tôi hồ sơ nơi nameNum = 1. Chúng tôi phải CAST() Tên trường vì nó sẽ phát triển với các lần truy cập tiếp theo; chúng ta cần đảm bảo rằng chúng ta CAST() nó đủ lớn để xử lý bất kỳ đầu ra nào; chúng tôi luôn có thể TRIM() sau này, nếu cần. Chúng tôi không phải chỉ định bí danh cho các trường vì chữ ký CTE cung cấp các bí danh đó.Trường hợp đệ quy (sau UNION ALL) tham gia CTE hiện tại với CTE trước, đảm bảo rằng các lần truy cập tiếp theo sử dụng các giá trị tênNum cao hơn bao giờ hết. Chúng tôi cần phải TRIM() các lần lặp trước của Tên, sau đó thêm dấu phẩy và Tên mới. Kết quả sẽ được, rõ ràng, CAST() ed đến một trường lớn hơn.
Truy vấn chính thức lấy chỉ các lĩnh vực chúng tôi quan tâm (myid, Tên) và, trong subquery, châm chọc tái sắp xếp các hồ sơ để các namesJoined.nameCount giá trị cao nhất sẽ nhận được 1 như giá trị finalSort. Sau đó, chúng tôi yêu cầu mệnh đề WHERE chỉ cung cấp cho chúng tôi một bản ghi này (cho mỗi giá trị myId).
Có, tôi đã đặt bí danh truy vấn con là tmp, tức là bạn có thể nhận được thông tin chung. Hầu hết các công cụ SQL yêu cầu bạn cung cấp cho một truy vấn phụ một bí danh, ngay cả khi đó là mối quan hệ duy nhất có thể nhìn thấy tại thời điểm đó.
bản sao có thể có của [SQL Server: Tôi có thể Comma phân định nhiều hàng vào một cột không?] (Http://stackoverflow.com/questions/2046037/sql-server-can-i-comma-delimit-multiple-rows- thành một cột) –
Bản sao bạn đề xuất không bao gồm sử dụng CTE để thực hiện việc này. –