如何使用 table 值参数进行条件连接?
How to do a conditional JOIN with table valued parameter?
好的,所以我花了一些时间研究这个问题,但似乎找不到好的解决方案。
我目前正在创建一个带有一组可选参数的存储过程。存储过程将充当多个 table 和列的 "universal search query"。
存储过程看起来像这样(请记住,这只是精简版,实际存储过程有更多列等)
“@ProductIdsParam IntList READONLY”是一个 table 值参数示例,如果它不为空,我想加入。换句话说,查询应该只搜索不是 null/empty 的参数。
调用过程和解析其他参数的工作就像它应该的那样。然而,我可能误解了,根本不应该做这样的 "universal search query"。
CREATE PROCEDURE [dbo].[usp_Search]
@ProductIdParam INT = NULL,
@CustomerNameParam NVARCHAR(100) = NULL,
@PriceParam decimal = NULL,
-- THIS IS WHAT I'D LIKE TO JOIN. BUT THE TABLE CAN BE EMPTY
@ProductIdsParam IntList READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT
CustomerTransactionTable.first_name AS FirstName,
CustomerTransactionTable.last_name AS LastName,
ProductTable.description AS ProductDescription,
ProductTable.price as ProductPrice
FROM dbo.customer AS CustomerTransactionTable
-- JOINS
LEFT JOIN dbo.product AS ProductTable
ON CustomerTransactionTable.product_id = ProductTable.id
WHERE
(ProductTable.id = @ProductIdParam OR @ProductIdParam IS NULL)
AND (CustomerTransactionTable.first_name = @CustomerNameParam OR @CustomerNameParam IS NULL)
AND (CustomerTransactionTable.price = @PriceParam OR @PriceParam IS NULL)
END
您可以在 LEFT join 中添加 int table,然后在 filter table 中添加一个基于记录数的 where 条件。如果@ProductIdsParam声明为table,你应该先计算其中的记录并将结果存储在变量中。
AND COALESCE(@ProductIdsParam.id, 0) = (CASE WHEN @ProductIdsCount = 0 THEN 0 ELSE ProductTable.id END)
如果@ProductIdsCount = 0 那么你总是得到 0 = 0 所以你得到所有记录,否则你 select 只记录过滤器 table 中的 productId 等于 ProductTable.id.
虽然还有其他(可能更清洁)的方法,但我认为这可行。
好的,所以我花了一些时间研究这个问题,但似乎找不到好的解决方案。
我目前正在创建一个带有一组可选参数的存储过程。存储过程将充当多个 table 和列的 "universal search query"。
存储过程看起来像这样(请记住,这只是精简版,实际存储过程有更多列等)
“@ProductIdsParam IntList READONLY”是一个 table 值参数示例,如果它不为空,我想加入。换句话说,查询应该只搜索不是 null/empty 的参数。
调用过程和解析其他参数的工作就像它应该的那样。然而,我可能误解了,根本不应该做这样的 "universal search query"。
CREATE PROCEDURE [dbo].[usp_Search]
@ProductIdParam INT = NULL,
@CustomerNameParam NVARCHAR(100) = NULL,
@PriceParam decimal = NULL,
-- THIS IS WHAT I'D LIKE TO JOIN. BUT THE TABLE CAN BE EMPTY
@ProductIdsParam IntList READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT
CustomerTransactionTable.first_name AS FirstName,
CustomerTransactionTable.last_name AS LastName,
ProductTable.description AS ProductDescription,
ProductTable.price as ProductPrice
FROM dbo.customer AS CustomerTransactionTable
-- JOINS
LEFT JOIN dbo.product AS ProductTable
ON CustomerTransactionTable.product_id = ProductTable.id
WHERE
(ProductTable.id = @ProductIdParam OR @ProductIdParam IS NULL)
AND (CustomerTransactionTable.first_name = @CustomerNameParam OR @CustomerNameParam IS NULL)
AND (CustomerTransactionTable.price = @PriceParam OR @PriceParam IS NULL)
END
您可以在 LEFT join 中添加 int table,然后在 filter table 中添加一个基于记录数的 where 条件。如果@ProductIdsParam声明为table,你应该先计算其中的记录并将结果存储在变量中。
AND COALESCE(@ProductIdsParam.id, 0) = (CASE WHEN @ProductIdsCount = 0 THEN 0 ELSE ProductTable.id END)
如果@ProductIdsCount = 0 那么你总是得到 0 = 0 所以你得到所有记录,否则你 select 只记录过滤器 table 中的 productId 等于 ProductTable.id.
虽然还有其他(可能更清洁)的方法,但我认为这可行。