我有两张桌子:
产品:
ProductId | Name | Description
----------+-------+-------------------------------------
1 | shirt | this is description for shirt
2 | pent | this is description for pent
ProductOverride :
ProductOverrideId | ColumnId | Value | ProductId
------------------+-----------+------------------------+-----------
1 | 1 | overridden name | 1
2 | 2 | overridden description | 1
其中ColumnId
来自column_id
sys.columns
。
我想选择具有以下要求的所有产品:
如果在ProductOverride表中覆盖了产品名称或产品描述,请获取名称/描述的重写值,否则从产品表中获取名称/描述值。
示例输出:
ProductId | Name | Description
----------+-----------------+---------------------------
1 | overridden name | overridden description
2 | pent | this is description for pent
我有以下查询返回确切的结果。
DECLARE @productNameColumnId INT = 1;
DECLARE @productDescriptionColumnId INT = 2;
WITH OverriddenProductNameCTE ([Value], [ProductId]) AS
(
SELECT
temp.[Value], temp.ProductId
FROM
ProductOverride temp
WHERE
temp.ColumnId = @productNameColumnId
), OverriddenProductDescriptionCTE ([Value], [ProductId]) AS
(
SELECT
temp.[Value], temp.ProductId
FROM
ProductOverride temp
WHERE
temp.ColumnId = @productDescriptionColumnId
)
SELECT
p.ProductId,
CASE
WHEN EXISTS(SELECT [Value]
FROM OverriddenProductNameCTE opnc
WHERE opnc.ProductId = p.ProductId)
THEN (SELECT [Value]
FROM OverriddenProductNameCTE opnc
WHERE opnc.ProductId = p.ProductId)
ELSE p.[Name]
END AS [Name],
CASE
WHEN EXISTS(SELECT [Value]
FROM OverriddenProductDescriptionCTE opdc
WHERE opdc.ProductId = p.ProductId)
THEN (SELECT [Value]
FROM OverriddenProductDescriptionCTE opdc
WHERE opdc.ProductId = p.ProductId)
ELSE p.[Description]
END AS [Description]
FROM
product p
但是在CASE
语句中,我有以下重复代码:
SELECT [Value]
FROM OverriddenProductNameCTE opnc
WHERE opnc.ProductId = p.ProductId
表示如果CASE
语句的第一个条件为真,DBMS将在THEN
部分再次执行相同的查询。
我希望在简化查询和处理方面改进此查询。
此外,如果在这种情况下使用CTE有任何优势吗?
答案 0 :(得分:0)
如果它只有2列,我认为你能做的最简单的事情是连接两次加入:
SELECT p.ProductId
,COALESCE(poN.Value, p.Name) As Name
,COALESCE(poD.Value, p.Description) As Description
FROM Product p
LEFT JOIN ProductOverride poN ON p.ProductId = poN.ProductId AND poN.ColumnId = 1
LEFT JOIN ProductOverride poD ON p.ProductId = poD.ProductId AND poD.ColumnId = 2
如果它是更多列,我会建议转动ProductOverride表并离开连接 - 就像这样(一个完整的例子):
创建并填充样本表(请在将来的问题中保存此步骤)
CREATE TABLE Product
(
ProductId int,
Name varchar(100),
Description varchar(100),
price int null
);
INSERT INTO Product VALUES
(1, 'shirt', 'Description for shirts', 1),
(2, 'Pants', 'Description for pants', 4),
(3, 'Socks', 'Description for socks', 5)
CREATE TABLE ProductOverride
(
ProductOverrideId int,
ColumnId int,
Value varchar(100),
ProductId int
);
INSERT INTO ProductOverride VALUES
(1,1,'product 1 name',1),
(2,2,'product 1 desc',1),
(3,3,'7',1),
(4,1,'pants name',2),
--Note: no pants description in the override tabl
(6,3,'8',2);
-- Note: no socks at all in override table
查询:
SELECT p.ProductId
,COALESCE(override.[1], p.Name) As Name
,COALESCE(override.[2], p.Description) As Description
,COALESCE(CAST(override.[3] as int), p.Price) As Price
FROM Product p
LEFT JOIN
(
SELECT *
FROM
(
SELECT ProductId, Value, ColumnId -- Columns To use for pivot
FROM ProductOverride
) ColumnsToPivot
PIVOT (
max (Value)
for ColumnId in ([1], [2], [3]) -- Values in ColumnId column to make the column names
) as pivotedData
) as override ON p.ProductId = override.ProductId
结果:
ProductId Name Description Price
1 product 1 name product 1 desc 7
2 pants name Description for pants 8
3 Socks Description for socks 5