我有以下我正在构建的SQL语句,它根据表中的值的顺序返回一系列值,用于'产品数据'
例如,产品,电视,具有屏幕尺寸,我们希望根据用户配置在具有指定范围之间的屏幕的电视上进行查询。所以他们可能会说,给我替代电视3个尺寸,两边都是42"。
此查询仅根据指定的产品执行此操作:
DECLARE @ProductType INT = (
SELECT p.prod_ptype_id
FROM product p
WHERE p.prod_id = @ProductId
)
DECLARE @AttributeId INT = (
SELECT at.aptype_attr_id
FROM Attribute_ProductType at
INNER JOIN Attribute a
ON a.attr_id = at.aptype_attr_id
WHERE ISNULL(a.ReplacementTolerant, 0) = 1
AND at.aptype_ptype_id = @ProductType
)
DECLARE @ToleranceRange INT = (
SELECT a.ToleranceRange
FROM Attribute_ProductType at
INNER JOIN Attribute a
ON a.attr_id = at.aptype_attr_id
WHERE ISNULL(a.ReplacementTolerant, 0) = 1
AND at.aptype_ptype_id = @ProductType
)
DECLARE @AttributeValueIndex INT = (
SELECT DISTINCT ( av.attrval_index )
FROM Product_Attribute pa
INNER JOIN AttributeValue av
ON av.attrval_attr_id = pa.pattr_attr_id
WHERE av.attrval_id = (
SELECT pattr_attrval_id
FROM product_attribute pa3
WHERE pa3.pattr_prod_id = @ProductId
AND pa3.pattr_attr_id = @AttributeId
)
);
WITH ProductTypeAttributes
AS (
SELECT DISTINCT attrval_val
,attrval_index
,ROW_NUMBER() OVER ( ORDER BY attrval_index ) AS RowNumber
FROM Product_Attribute pa
INNER JOIN AttributeValue av
ON av.attrval_id = pa.pattr_attrval_id
INNER JOIN Product p
ON p.prod_id = pa.pattr_prod_id
WHERE pa.pattr_attr_id = @AttributeId
AND p.prod_ptype_id = @ProductType
GROUP BY attrval_val
,attrval_index
)
SELECT *
FROM ProductTypeAttributes
WHERE RowNumber >= (
(SELECT DISTINCT ( RowNumber )
FROM ProductTypeAttributes pta2
WHERE attrval_index = @AttributeValueIndex)
) - @ToleranceRange
AND ( RowNumber <= (
SELECT DISTINCT ( RowNumber )
FROM ProductTypeAttributes pta3
WHERE attrval_index = @AttributeValueIndex
) + @ToleranceRange )
这一切都很好,并且完全按照我需要的方式工作,虽然它可能需要一些优化,但是现在我只是希望能够将它作为POC所需要的地方。 / p>
显而易见的选择是将其作为一个表格功能 - 但是当我有这些声明时,我不知道要应用什么语法?#39;声明&#39;语句。
我已经查看了MSDN和样本,这些样本显示了我认为需要实现的类似样本,但我无法理解如何将declare语句与表结合使用以这种方式运作。
任何人都可以对此有所了解吗?
谢谢!
答案 0 :(得分:0)
我无法在我愿意投入的时间内将整个查询快速转换为内联函数,尤其是在不了解表中的内容及其相关性的情况下。但是,我相信我在下面的内容至少会替换你的前4个选项,并且可以重复使用。我相信使用相同的概念你可以将查询的其余部分合并到这个函数中 - 或者可能是第二个函数用于更多的模块化。在尝试转换之前,最好先进行优化。
CREATE FUNCTION GetProductInfo
(
@ProductID int
)
RETURNS TABLE
AS
RETURN
SELECT
p.prod_ptype_id AS ProductType,
at.aptype_attr_id AS AttributeId,
a.ToleranceRange AS ToleranceRange
av.attrval_index AS AttributeValueIndex
FROM product p
INNER JOIN Attribute_ProductType at
ON at.aptype_ptype_id = p.prod_ptype_id
INNER JOIN Attribute a
ON a.attr_id = at.aptype_attr_id
AND a.ReplacementTolerant = 1
-- This next section got a little confusing for me. Knowing more about what is in the various tables would help me figure out which tables
-- might produce duplicate rows requiring the CROSS APPLY TOP 1 construct and which could be simple JOINs.
-- Also, you are using Product_Attribute twice in the same query for @AttributeValueIndex in a confusing (to me) way, so I attempted to simplify here.
CROSS APPLY (
SELECT
TOP 1 *
FROM product_attribute pa_all
WHERE pa_all.pattr_prod_id = p.prod_ptype_id
AND pa_all.pattr_attr_id = at.aptype_attr_id
) AS pa
INNER JOIN AttributeValue av
ON av.attrval_attr_id = pa.pattr_attr_id
AND av.attrval_id = pa.pattr_attrval_id
WHERE p.prod_id = @ProductId;
GO
DECLARE
@ProductType INT
@AttributeId INT
@ToleranceRange INT,
@AttributeValueIndex INT;
SELECT
@ProductType = ProductType,
@AttributeId = AttributeId,
@ToleranceRange = ToleranceRange,
@AttributeValueIndex = AttributeValueIndex
FROM GetProductInfo
(
@ProductID
);
答案 1 :(得分:0)
部署我以前的评论,而不是内联,我最终使用了多语句表函数:
CREATE FUNCTION GetAttributeToleranceRange
(
@ProductId int
)
RETURNS @ProductTypeToleranceRange TABLE
(
prod_type int,
attr_id int,
attrval_val nvarchar(max),
attrval_index int,
RowNumber int
)
AS BEGIN
DECLARE @ProductTypeAttributesTable TABLE
(
attrval_val nvarchar(max),
attrval_index int,
RowNumber int
)
declare @ProductType int
declare @AttributeId int
declare @ToleranceRange int
declare @AttributeValueIndex int
SELECT @ProductType = (SELECT p.prod_ptype_id FROM product p WHERE p.prod_id=@ProductId)
SELECT @AttributeId = (SELECT at.aptype_attr_id FROM Attribute_ProductType at INNER JOIN Attribute a ON a.attr_id = at.aptype_attr_id WHERE ISNULL(a.ReplacementTolerant,0)=1 AND at.aptype_ptype_id = @ProductType)
SELECT @ToleranceRange = (SELECT a.ToleranceRange FROM Attribute_ProductType at INNER JOIN Attribute a ON a.attr_id = at.aptype_attr_id WHERE ISNULL(a.ReplacementTolerant,0)=1 AND at.aptype_ptype_id = @ProductType)
SELECT @AttributeValueIndex = (SELECT DISTINCT(av.attrval_index) FROM Product_Attribute pa INNER JOIN AttributeValue av ON av.attrval_attr_id=pa.pattr_attr_id WHERE av.attrval_id = (SELECT pattr_attrval_id FROM product_attribute pa3 WHERE pa3.pattr_prod_id=@ProductId and pa3.pattr_attr_id=@AttributeId));
INSERT @ProductTypeAttributesTable SELECT DISTINCT attrval_val, attrval_index, ROW_NUMBER() OVER (ORDER BY attrval_index) As RowNumber
FROM Product_Attribute pa
INNER JOIN AttributeValue av ON av.attrval_id = pa.pattr_attrval_id
INNER JOIN Product p ON p.prod_id = pa.pattr_prod_id
WHERE pa.pattr_attr_id = @AttributeId AND p.prod_ptype_id = @ProductType
GROUP BY attrval_val, attrval_index;
INSERT @ProductTypeToleranceRange SELECT @ProductType, @AttributeId, * FROM @ProductTypeAttributesTable WHERE RowNumber >= ((SELECT DISTINCT(RowNumber) FROM @ProductTypeAttributesTable pta2 WHERE attrval_index=@AttributeValueIndex)) - @ToleranceRange AND (RowNumber <= (SELECT DISTINCT(RowNumber) FROM @ProductTypeAttributesTable pta3 WHERE attrval_index=@AttributeValueIndex) + @ToleranceRange)
RETURN
END
同样,它会从一些优化中受益,但它确实在我需要的地方使用单一参数时可以提供我需要的东西。