根據您的意見,我不認爲使用STUFF與FOR XML如果最好的方式來處理這一點。通常,將多行連接成單個字符串的最佳方法是使用遞歸公用表表達式(CTE)。
有一些使用CTE(和一些替代方法)here的例子。
我已經調整了其中一個CTE選項來執行類似於您所描述的操作。
首先,我已經建立了一個簡單的表格,類似於你所描述的數據:然後我用一個CTE是建立一個汽車牌照和值附加的數據集
create table #cars (CarMake varchar(50), CarModel varchar(50), CarValue INT, OwnerName varchar(50), LicenseID varchar(50));
insert into #cars(CarMake, CarModel, CarValue, OwnerName, LicenseID) values ('Toyota','Camry', 12000, 'Steve','ABC123');
insert into #cars(CarMake, CarModel, CarValue, OwnerName, LicenseID) values ('Toyota','Camry', 12000, 'Bob','HED999');
insert into #cars(CarMake, CarModel, CarValue, OwnerName, LicenseID) values ('Toyota','Camry', 19000, 'Helen','WKS444');
insert into #cars(CarMake, CarModel, CarValue, OwnerName, LicenseID) values ('Ford','Mustang',30000, 'Amy','JKJL88');
insert into #cars(CarMake, CarModel, CarValue, OwnerName, LicenseID) values ('Ford','Mustang',30000, 'Billy-Bob','EZ1111');
insert into #cars(CarMake, CarModel, CarValue, OwnerName, LicenseID) values ('Aston Martin','Vantage',90000, 'Mike','HY7733');
/按品牌/型號彙總。可變@FlagOwnerName控制是否從CTE或這些值從源表的基本值在最終SELECT語句中使用:
DECLARE @FlagOwnerName bit = 1;
WITH cte (CarMake, CarModel, CarValueTotal, Car_Val, LicenseList, License_ID, length_)
AS
(
SELECT
CarMake, CarModel, 0, 0, CAST('' AS VARCHAR(8000)), CAST('' AS VARCHAR(8000)), 0
FROM #cars
GROUP BY CarMake, CarModel
UNION ALL
SELECT c.CarMake, c.CarModel, cte.CarValueTotal + c.CarValue, c.CarValue,
CAST(cte.LicenseList + CASE WHEN length_ = 0 THEN '' ELSE ', ' END + c.LicenseID AS VARCHAR(8000)),
CAST(LicenseID AS VARCHAR(8000)),
length_ + 1
FROM cte
INNER JOIN #cars c ON cte.CarMake = c.CarMake AND cte.CarModel = c.CarModel
WHERE c.LicenseID > cte.License_ID
)
SELECT
cars.CarMake,
cars.CarModel,
CASE WHEN @FlagOwnerName = 1 THEN cars.OwnerName ELSE 'ALL' END as OwnerName,
CASE WHEN @FlagOwnerName = 1 THEN cars.CarValue ELSE totals.CarValueTotal END as CarValue,
CASE WHEN @FlagOwnerName = 1 THEN cars.LicenseID ELSE totals.LicenseList END as LicenseID
FROM #cars cars
INNER JOIN
(
SELECT CarMake, CarModel, LicenseList, CarValueTotal
FROM (
SELECT CarMake, CarModel, LicenseList, CarValueTotal,
RANK() OVER (PARTITION BY CarMake, CarModel ORDER BY length_ DESC)
FROM CTE
) D (CarMake, CarModel, LicenseList, CarValueTotal, rank)
WHERE rank = 1
) totals ON cars.CarMake = totals.CarMake AND cars.CarModel = totals.CarModel
GROUP BY
cars.CarMake,
cars.CarModel,
CASE WHEN @FlagOwnerName = 1 THEN cars.OwnerName ELSE 'ALL' END,
CASE WHEN @FlagOwnerName = 1 THEN cars.CarValue ELSE totals.CarValueTotal END,
CASE WHEN @FlagOwnerName = 1 THEN cars.LicenseID ELSE totals.LicenseList END
所以當@FlagOwnerName = 1,我們得到:
CarMake CarModel OwnerName CarValue LicenseID
Aston Martin Vantage Mike 90000 HY7733
Ford Mustang Amy 30000 JKJL88
Ford Mustang Billy-Bob 30000 EZ1111
Toyota Camry Bob 12000 HED999
Toyota Camry Helen 19000 WKS444
Toyota Camry Steve 12000 ABC123
而當@FlagOwnerName = 0,我們得到:
CarMake CarModel OwnerName CarValue LicenseID
Aston Martin Vantage ALL 90000 HY7733
Ford Mustang ALL 60000 EZ1111, JKJL88
Toyota Camry ALL 43000 ABC123, HED999, WKS444
注意,在你的評論暗示你不想返回OWNERNAME當@FlagOwnerName = 0,而這是可能的我在存儲過程(即,根據參數執行不同的查詢)我不會推薦它。最好是返回一組一致的列,如果您在報告頂部使用報告工具,那麼您可能會在其中包含一些邏輯以根據參數值隱藏列。
你的意思是你想用CREATE FUNCTION語句創建一個實際的SQL Server函數嗎?或者你只是想與你的SELECT語句內聯?這也有助於瞭解您正在使用的SQL Server版本。 – Nathan
不好意思,這將成爲重複調用的存儲過程的一部分。數據庫在SQL Server 2008上。 – am109
我想你可能需要更多地解釋你正在嘗試做什麼 - 你對「LicenseIDs」有什麼期望?在XML上使用STUFF函數的目的是什麼?你是否期望Cars1與Cars2成爲一對多的關係? – Nathan