避免UNION查询

时间:2017-02-01 08:51:34

标签: sql sql-server database

我有一个包含Products和Salespeople表的数据库。 每个产品由销售人员销售,因此有一个FK-PK链接 在Products.SalespersonIdSalespeople.Id之间。没什么不寻常的。

我们可以拥有一名“属于”销售员的子销售员, 以便该表具有可为空的ParentSalespersonId列 这是“猪的耳朵”FK回到Salespeople.Id PK。

选择由所选销售人员销售的产品是微不足道的, 但选择所选销售员的子销售人员销售的产品需要UNION

SELECT *
  FROM Products
 INNER JOIN Salespeople ON Salespeople.Id = Products.SalespersonId
 WHERE Salespeople.Id = <some vale> -- products sold directly

UNION

SELECT *
  FROM Products
 INNER JOIN Salespeople AS Sub ON Sub.Id = Products.SalespersonId
 INNER JOIN Salespeople AS Parent
         ON Parent.Id = Sub.ParentSalespersonId
 WHERE Parent.Id = <some vale>-- products sold indirectly

除了丑陋之外,UNION导致性能损失,因为需要执行两个查询而不是一个查询。

多年来我创建了许多数据库,并编写了100个查询, 但我无法理解这一个...

如何重新构建表格以实现所需的关系,但不再需要那些丑陋的UNION和第二个SELECT

由于

3 个答案:

答案 0 :(得分:1)

您只需一个查询即可:

SELECT *
FROM Products as P
    INNER JOIN Salespeople Sub ON Sub.Id = P.SalespersonId
    LEFT OUTER JOIN Salespeople AS Parent ON Parent.Id = Sub.ParentSalespersonId
WHERE 
    Sub.Id = <some vale> -- products sold directly
    or Parent.Id = <some vale>-- products sold indirectly

答案 1 :(得分:1)

你不能简单地做:

SELECT *
FROM Products
INNER JOIN Salespeople AS Sub ON Sub.Id = Products.SalespersonId
LEFT JOIN Salespeople AS Parent
       ON Parent.Id = Sub.ParentSalespersonId
WHERE Parent.Id = <some vale>
   OR Salespeople.Id = <some vale>

正如Jodrell在评论中提到的那样,建议明确选择所需的列,而不是*

答案 2 :(得分:0)

ERM,

SELECT
            * -- don't use SELECT *
    FROM
            [dbo].[Products] P
        LEFT JOIN
            [dbo].[Salespeople] I
                ON I.[Id] = P.[SalespersonId]
        LEFT JOIN
            [dbo].[Salespeople] S
                ON S.[Id] = P.[SalespersonId]
        LEFT JOIN
            [dbo].[Salespeople] P
                ON P.[Id] = S.[ParentSalespersonId]
    WHERE
            I.[Id] IS NOT NULL
        OR
            P.[Id] IS NOT NULL;