将select语句中的子查询重构为连接

时间:2016-04-08 10:33:24

标签: sql sql-server sql-server-2008 tsql

我有一张产品表和一个小工具表。

产品是由许多小部件构建的,我有一个链接表,显示哪些小部件链接到哪些产品。

小工具可以标记为expired,这意味着它们不符合添加到任何新产品的条件。

以下 sqlFiddle -

中的架构和示例数据

我想要一个查询,根据以下规则显示特定产品的所有符合条件的小部件:

  1. 如果小部件被标记为已过期,则不应显示小部件。
  2. 作为上述规则的例外情况 - 如果窗口小部件被标记为已过期但已链接到产品,则应显示该窗口小部件。
  3. 如果窗口小部件已与产品相关联,则应将其标记为'selected'
  4. 我已经得到以下有效的查询,并且满足以上所有规则:

    select 
        data.WidgetName, 
        data.expired,
        case 
            when data.ID in (select data_id from Widget_link where productId = 1)   
            then 1 
            else 0 
        end as selected
    from Widget_data data
    left outer join Widget_link link
        on data.ID = link.data_id and data.expired = 1
    where (data.expired = 0 or (data.expired = 1 and link.productId = 1))
    

    我想找到一种方法将查询的select部分中的子查询重构为某种连接。我试图创建一个我只能使用where子句过滤的视图,而不是在两个地方使用productId。这可能吗?

2 个答案:

答案 0 :(得分:3)

在简化时,您的查询可以单独根据JOIN进行评估,如下所示,根本不需要内部查询。

select data.WidgetName,
     case when link.id is not null then 1 else 0 end as selected
from Widget_data data
left outer join Widget_link link
    on data.ID = link.data_id and link.productId = 1
where data.expired=0 or link.id is not null

<强> Demo SQL fiddle

答案 1 :(得分:0)

您可以使用SQL CTE (Common Table Expression)来涵盖SELECT列表中的结果,并在单个SQL语句中使用

您甚至可以在代码中创建SQL statements with multiple CTE's

我建议的内容可以直观地概括如下

and you'd be in a bit of a mess. If you use