首页 > 解决方案 > 连接子行同时尊重 Where 子句与或

问题描述

我有一个问题,我需要将子表的值连接到一个字段中,同时还要尊重 where 子句中的 OR 条件。假设我在 Northwind 数据库中工作,并且我有一个查询,例如:

SELECT c.CategoryName, p.ProductName FROM Products p join Categories c on p.CategoryID = c.CategoryID
where c.CategoryName like '%on%' or p.ProductName = 'Vegie-spread'
order by c.CategoryName, p.ProductName

我希望将所有产品名称连接到每个类别名称的一个字段中,以便 Products 字段如下所示:

Aniseed Syrup-Chef Anton's Cajun Seasoning-Chef Anton's Gumbo Mix-etc.

我的第一次尝试如下所示:

select c.CategoryName, ISNULL(products.line, '') AS ProductNames
    from Categories c
    cross apply (
        select CAST((select p.ProductName + '-'
        from products p
        where c.CategoryID = p.CategoryID
        and (c.CategoryName like '%on%' or p.ProductName = 'Vegie-spread')
        order by p.ProductName
        for xml path('')) as nvarchar(max)) line
    ) products
order by c.CategoryName

但这会返回一些与 where 条件不匹配的类别。我希望结果就像我输入了这个查询一样:

SELECT c.CategoryName, p.ProductName FROM Products p join Categories c on p.CategoryID = c.CategoryID
where c.CategoryName like '%on%' or p.ProductName = 'Vegie-spread'
order by c.CategoryName, p.ProductName

除了我希望每个类别有一行与查询匹配的所有产品连接。

有人可以告诉我如何做到这一点吗?

标签: sql-serverconcatenationcross-apply

解决方案


“蛮力”吧。从您的“好像”查询开始:

SELECT c.CategoryName, p.ProductName FROM Products p join Categories c on p.CategoryID = c.CategoryID
where c.CategoryName like '%on%' or p.ProductName = 'Vegie-spread'
order by c.CategoryName, p.ProductName

并将其用作 CTE 或派生表,然后将您的FOR XML PATH逻辑应用于该 CTE 而不是基表,以将产品行“组合”成一个。

这是一个问题,显示了在 SQL Server 中执行“组连接”的几种方法

所以在伪代码中,使用 CTE 看起来像这样:

WITH cte AS (
  {Your "as-if" query}
)
SELECT CategoryName, ({code that does a group concat}) AS ProductLine
FROM cte

在这{code that does a group concat}部分(无论您决定这样做)中,您类似地将您的实际表名替换为cte.


推荐阅读