0

我从来没有在 MySQL 中使用 IN 获得过良好的性能,并且我再次遇到了性能问题。

我正在尝试创建一个视图。它的相关部分是:

SELECT
  c.customer_id,
  ....
  IF (c.customer_id IN (
            SELECT cn.customer_id FROM customer_notes cn
        ), 1, 0) AS has_notes
  FROM customers c;

基本上,我只想知道客户是否附有便条。多少个音符都没有关系。如何使用 JOIN 重写它以加快速度?

客户表目前有 150 万行,因此性能是一个问题。

4

3 回答 3

1

我认为EXISTSJOINor更适合您的情况IN

SELECT 
   IF (EXISTS ( 
        SELECT *
        FROM customer_notes cn 
        WHERE c.customer_id = cn.customer_id),
       1, 0) AS filter_notes 
FROM customers 
于 2010-12-16T23:27:49.727 回答
1

您不需要选择客户 ID 吗?就目前而言,您不是为每个客户运行一次子查询,并获得一连串真值或假值而不知道哪个值适用于哪个客户?

如果这是您需要的,则不需要引用客户表(除非您将数据库保持在语义不完整的状态,并且 customer_notes 中可能存在没有相应客户的条目 - 但是您会遇到更大的问题比这个查询的性能);你可以简单地使用:

SELECT DISTINCT Customer_ID
  FROM Customer_Notes
 ORDER BY Customer_ID;

获取 Customer_Notes 表中至少包含一个条目的客户 ID 值列表。

如果您需要客户 ID 值列表和关联的真/假值,则需要进行联接:

SELECT C.Customer_ID,
       CASE WHEN N.Have_Notes IS NULL THEN 0 ELSE 1 END AS Has_Notes
  FROM Customers AS C
  LEFT JOIN (SELECT Customer_ID, COUNT(*) AS Have_Notes 
               FROM Customer_Notes
              GROUP BY Customer_ID) AS N
    ON C.Customer_ID = N.Customer_ID
 ORDER BY C.Customer_ID;

如果这导致性能不佳,请检查您在 Customer_Notes.Customer_ID 上是否有索引。如果这不是问题,请研究查询计划。


做不到……在视图中

在任何 DBMS 中,对视图中允许的内容的微小限制总是令人讨厌(MySQL 并不是唯一有限制的)。但是,我们可以通过单个常规连接来完成。我刚想起来。 COUNT(column)只计算非空值,如果所有值都为空,则返回 0,所以 - 如果你不介意得到一个计数而不仅仅是 0 或 1 - 你可以使用:

SELECT C.Customer_ID,
       COUNT(N.Customer_ID) AS Num_Notes
  FROM Customers AS C
  LEFT JOIN Customer_Notes AS N
    ON C.Customer_ID = N.Customer_ID
 GROUP BY C.Customer_ID
 ORDER BY C.Customer_ID;

如果你绝对必须有 0 或 1:

SELECT C.Customer_ID,
       CASE WHEN COUNT(N.Customer_ID) = 0 THEN 0 ELSE 1 END AS Has_Notes
  FROM Customers AS C
  LEFT JOIN Customer_Notes AS N
    ON C.Customer_ID = N.Customer_ID
 GROUP BY C.Customer_ID
 ORDER BY C.Customer_ID;

请注意,“N.Customer_ID”的使用至关重要——尽管表中的任何列都可以(但你没有透露任何其他列的名称,AFAICR),我通常会使用连接列以外的其他内容明晰。

于 2010-12-16T23:44:31.953 回答
0

尝试这个

SELECT
  CASE WHEN cn.customer_id IS NOT NULL THEN 1
        ELSE 0
    END     AS filter_notes
  FROM customers c LEFT JOIN customer_notes cn
    ON c.customer_id= cn.customer_id
于 2010-12-16T23:29:17.950 回答