【问题标题】:SQL best alternative to a LEFT JOIN and WHERE statement?SQL LEFT JOIN 和 WHERE 语句的最佳替代方案?
【发布时间】:2018-10-31 10:45:00
【问题描述】:

基本上我有两张桌子。客户和采购表。我的问题是购买表非常大并导致性能问题,我正在尝试将我的代码组织到相关的 CTE 中。

我正在尝试提取购买了 A 型吉他或没有购买的人的所有购买记录。

我想过滤掉任何没有购买 GuitarType A 但仍保留没有购买任何东西的客户。

这是我的代码:

WITH Purchases AS 
(
    SELECT
        , CustID
        , GuitarType
    FROM
        Purchase
    WHERE
        GuitarType = 'A'
)
,
RelevantCustomers AS
(
    SELECT
        P.Custid
        , P.PurchaseDate
        , C.CustType
    FROM
        Customer

)
SELECT
    Custid
    , GuitarType
    , PurchaseDate
FROM
    Purchases AS p
INNER JOIN
    RelevantCustomers AS rc ON p.CustId= rc.CustId

客户:

  +--------+-------------+----------+
    | CustId | CreatedDate | CustType |
    +--------+-------------+----------+
    | 1      | 01/01/2017  | A        |
    +--------+-------------+----------+
    | 2      | 01/01/2018  | B        |
    +--------+-------------+----------+
    | 4      | 01/01/2018  | C        |
    +--------+-------------+----------+

购买

+----------+--------------+------------+
| GuitarId | PurchaseDate | GuitarType |
+----------+--------------+------------+
| 1        | 04/01/2018   | A          |
+----------+--------------+------------+
| 1        | 05/01/2018   | A          |
+----------+--------------+------------+
| 1        | 06/01/2018   | C          |
+----------+--------------+------------+
| 2        | 06/01/2018   | A          |
+----------+--------------+------------+
| 2        | 06/01/2018   | B          |
+----------+--------------+------------+
| 2        | 06/01/2018   | A          |
+----------+--------------+------------+

如果我使用 INNER JOIN,那么它只会返回那些购买 Guitar Type A 的人。如果我使用 LEFT,那么它将包括所有客户。

另一种方法是将“Where GuitarType = 'A' 移至 where 子句并执行 LEFT JOIN,但这会导致我的代码杂乱无章,并可能出现一些性能问题。

【问题讨论】:

  • 如果您的代码运行速度非常慢,请查看结构并添加索引,而不会使简单查询变得复杂。如果设计得当,即使有数百万行,也不应该成为问题
  • 您的“当前代码”将返回错误,因为 P 不是在您的第二个 CTE 的 FROM 子句中创建的,而是在 SELECT 列表中引用的。
  • @Sewder 。 . .假设如果客户购买了东西,那么guitartype 不是NULL 是否合理?对于一个没有购买任何东西的客户来说,拉取购买记录是什么意思?
  • 我建议你尝试为 GuitatType = 'A' 选择购买并使用子查询获取客户信息,然后与所有没有购买任何东西的客户联合。另外我认为在采购表中对 CustomerID 有索引是必要的。

标签: sql-server tsql


【解决方案1】:

这可能会成功

SELECT rc.Custid, p.GuitarType, p.PurchaseDate
  FROM RelevantCustomers rc 
  LEFT JOIN Purchases p 
    ON p.CustId = rc.CustId
  LEFT JOIN Purchases pn 
    ON pn.CustId = rc.CustId 
   AND p.GuitarType != 'A'
 WHERE (p.GuitarType = 'A' OR p.CustID IS NULL)  
   and  pn.CustID is null

【讨论】:

    【解决方案2】:

    你似乎想要:

    SELECT rc.Custid, p.GuitarType, p.PurchaseDate
    FROM RelevantCustomers rc LEFT JOIN
         Purchases p 
        ON p.CustId = rc.CustId
    WHERE p.GuitarType = 'A' OR p.GuitarType IS NULL;
    

    为了提高性能,您需要在Purchases(CustId) 上建立索引。

    【讨论】:

    • 如果购买的 GuitarType 可能为 NULL,这将不起作用。如果有人买了电缆怎么办? OP 的要求:“但仍然保留没有购买任何东西的客户。”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    相关资源
    最近更新 更多