有条件地加入表格

时间:2012-01-10 04:16:26

标签: sql tsql

我想在T-SQL查询中为表创建条件连接。此示例中使用的表来自Northwind数据库(只有一个附加表ProductCategories)

表产品和表类别具有多对多关系,因此表ProductCategories即将出现。

对于属于特定类别的每个产品,我需要表OrderDetails上的Quantity列总和。所以我有一个像下面的查询

Select p.ProductName, Sum(od.Quantity) As Qty
From Products p
    Join OrderDetails od On od.ProductID = p.ProductID
    Join ProductCategories pc On pc.ProductID = p.ProductID
        And pc.CategoryID = @CategoryID
Group By p.ProductName

@CategoryID是一个可选参数。因此,如果未提供,则不需要加入表ProductCategories 和查询应该如下所示

Select p.ProductName, Sum(od.Quantity) As Qty
From Products p
    Join OrderDetails od On od.ProductID = p.ProductID
Group By p.ProductName

我希望在不使用If条件(如下所示)重复整个查询的情况下实现此目的

If @CategoryID Is Null
    Select p.ProductName, Sum(od.Quantity) As Qty
    From Products p
        Join OrderDetails od On od.ProductID = p.ProductID
    Group By p.ProductName
Else
    Select p.ProductName, Sum(od.Quantity) As Qty
    From Products p
        Join OrderDetails od On od.ProductID = p.ProductID
        Join ProductCategories pc On pc.ProductID = p.ProductID
            And pc.CategoryID = @CategoryID
    Group By p.ProductName

这是查询的简化版本,其中包含许多其他表和条件,如ProductCategories。并且将需要多个If条件并重复查询。我也试过动态生成查询。它有效但查询根本不可读。

任何解决方案? 谢谢。

3 个答案:

答案 0 :(得分:2)

试试这个,如果你使用正确的参数化查询 - 不会对性能产生影响,但可能会有所收获:

Select p.ProductName, Sum(od.Quantity) As Qty
From Products p
    Join OrderDetails od On od.ProductID = p.ProductID
WHERE @CategoryID IS NULL OR EXISTS (SELECT * FROM ProductCategories WHERE CategoryID = @CategoryID AND ProductID = p.ProductID)
Group By p.ProductName

<强>实际上

在您的查询中

如果ProductCategories中的OrderDetails中的一行中有多行,那么您在SUM中会得到od.Quantity的重复项 - 是否是预期的行为吗

答案 1 :(得分:0)

我对T-SQL不太熟悉所以我不知道这是否会削减它,但在mysql中你可以做类似的事情

Select p.ProductName, Sum(od.Quantity) As Qty
From Products p
    Join OrderDetails od On od.ProductID = p.ProductID
    Join ProductCategories pc On pc.ProductID = p.ProductID
        And pc.CategoryID = if(@CategoryID is null , pc.CategoryID, @CategoryId)
Group By p.ProductName

是的,if()仍然存在但只是“一个查询”,如果这就是你要找的东西。

同时,您说您能够动态生成单个查询。如果是可读性那么大问题呢?如果您生成的查询比我上面提到的更符合我的意思,那么我会选择它。它是生成的;你赢了'手动调整/读取结果。

答案 2 :(得分:0)

我相信你可以加入表格与你正在进行的隐式内部联接。

在内连接中,它将源表上的键与目标表上的每个键实例匹配。

目标表上的每个匹配实例都会生成一组显示的行 匹配类型。

使用外部联接,它将显示源行,如果另一个表中没有匹配的行。如果存在它将基本上与内连接相同,并且您将为每个匹配实例返回一行。因此,您可以获得所需的数据,而不是获取哪些数据不可用。

以此为例

select * from Products

    Left join ProductAndCategory on ProductAndCategory.ProductID = Products.ProductID
    left join Categories on Categories.CategoryID = ProductAndCategory.CategoryID

我有一个简单的Product表格,其中包含ProductIDProductName一个ProductAndCategory表格,其中包含ProductIDCategoryID以及Categories表格CategoryIDCategoryName

它将显示具有已连接类别的类别的行,而没有类别的行将仅显示对于不存在的值为null的一行。