へ
AND (@FlagOwnerName = 0 OR Cars2.OwnerName = Cars1.OwnerName)
あなたのコメントに基づいて最良の方法はこれに接近した場合、私はXML FORとSTUFFを使用しないと思います。通常、複数の行を1つの文字列に連結する最良の方法は、再帰的な共通表式(CTE)を使用することです。
CTE(いくつかの別の方法)を使用する例がいくつかあります。here
CTEオプションの1つを、あなたが記述したものと似たようなことをするために採用しました。
まず、私はあなたが説明してきたデータに似たシンプルなテーブルを設定している:
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');
私は、車のライセンスと値が/追加されたデータセットを構築するためにCTEを使用しましたmake/modelによって集計されます。ソーステーブルからCTEまたはベース値からこれらの値は、最終的なSELECT文で使用されているかどうかの変数@FlagOwnerNameコントロール:
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
注意をあなたのコメントにあなたはとき@FlagOwnerName = 0これが可能である私ながらownernameには、返されたくなかった暗黙のことストアドプロシージャ(すなわち、パラメータに基づいて異なるクエリを実行する)私はそれをお勧めしません。一貫性のある一連の列が返されるようにすることをお勧めします。その上にレポートツールを使用する場合は、パラメータ値に基づいて列を非表示にするロジックをいくつか含めることができます。
CREATE FUNCTIONステートメントを使用して実際のSQL Server関数を作成することを意味しますか?または、SELECT文でインラインで処理したいだけですか?また、使用しているSQL Serverのバージョンを知ることもできます。 – Nathan
申し訳ありませんが、これは繰り返し呼び出されるストアドプロシージャの一部です。データベースはSQL Server 2008上にあります。 – am109
"LicenseIDs"に期待しているデータは何ですか? XMLでSTUFF関数を使用する目的は何ですか?あなたはCars1とCars2が1対多の関係になることを期待していますか? – Nathan