卡在mysql嵌套选择语句上

时间:2018-08-29 09:33:20

标签: mysql sql

我在select语句中加入了三个表:

表CRM_CONTACTS结构:

CONTACTS_ID, CONTACTS_EMAIL
1            email@email.com
2            email2@email.com

表CRM_PRODUCTS结构:

PRODUCTS_ID, PRODUCTS_NAME, PRODUCTS_TYPE
204          Sample         free_sample
205          beginners_1    monthly_subscription
206          beginners_2    monthly_subscription  

表CRM_PRODUCTS_PURCHASE:

ID, CONTACTS_ID, PRODUCTS_ID
3   1            204
4   1            205
5   2            204

因此客户当然可以购买多种产品。

我想做一个选择语句,选择所有购买PRODUCT_ID 204(免费样品)的客户,但是如果他们购买PRODUCT_TYPE = monthly_subscription的产品,我不希望他们出现在结果中

所以我想要的期望输出是与CONTACTS_ID 2的联系人。

我对sql语句很陌生。这是我到目前为止所得到的:

    SELECT CRM_PRODUCTS_PURCHASE.CONTACTS_ID,CRM_PRODUCTS_PURCHASE.PRODUCTS_ID, CRM_CONTACTS.CONTACTS_EMAIL, CRM_CONTACTS.CONTACTS_LANGUAGE
FROM CRM_PRODUCTS_PURCHASE
LEFT JOIN CRM_CONTACTS ON CRM_PRODUCTS_PURCHASE.CONTACTS_ID = CRM_CONTACTS.ID
LEFT JOIN CRM_PRODUCTS ON CRM_PRODUCTS_PURCHASE.PRODUCTS_ID = CRM_PRODUCTS.ID
WHERE CRM_PRODUCTS_PURCHASE.CONTACTS_ID IN 
(SELECT CRM_CONTACTS.ID
    FROM CRM_PRODUCTS_PURCHASE
        LEFT JOIN CRM_CONTACTS ON CRM_PRODUCTS_PURCHASE.CONTACTS_ID = CRM_CONTACTS.ID
        LEFT JOIN CRM_PRODUCTS ON CRM_PRODUCTS_PURCHASE.PRODUCTS_ID = CRM_PRODUCTS.ID
    WHERE CRM_PRODUCTS_PURCHASE.PRODUCTS_ID = 204 AND
        CRM_CONTACTS.CONTACTS_EMAIL!='' AND
        NOT coalesce(CRM_CONTACTS.CONTACTS_DEACTIVATED,0)
        GROUP BY CRM_CONTACTS.CONTACTS_EMAIL
        ORDER BY CRM_CONTACTS.CONTACTS_LANGUAGE)

2 个答案:

答案 0 :(得分:0)

首先您提到ORDER BY CRM_CONTACTS.CONTACTS_LANGUAGE,它不在     SELECT语句。您如何在子查询中使用GROUP BY返回单列。

(SELECT CRM_CONTACTS.ID
    FROM CRM_PRODUCTS_PURCHASE
        LEFT JOIN CRM_CONTACTS ON CRM_PRODUCTS_PURCHASE.CONTACTS_ID = CRM_CONTACTS.ID
        LEFT JOIN CRM_PRODUCTS ON CRM_PRODUCTS_PURCHASE.PRODUCTS_ID = CRM_PRODUCTS.ID
    WHERE CRM_PRODUCTS_PURCHASE.PRODUCTS_ID = 204 AND
        CRM_CONTACTS.CONTACTS_EMAIL!='' AND
        NOT coalesce(CRM_CONTACTS.CONTACTS_DEACTIVATED,0)
        GROUP BY CRM_CONTACTS.CONTACTS_EMAIL
        ORDER BY CRM_CONTACTS.CONTACTS_LANGUAGE)

答案 1 :(得分:0)

您应该尽可能避免使用嵌套子选择,因为它们很难使MySQL内部优化器使用,因此倾向于生成非常慢的查询。在许多情况下,创建一个包含子选择数据的临时表并进行连接通常比进行子选择要好,但这确实是一种情况。

但是有时您需要这样做,在这种情况下,请尝试使子选择尽可能简单。

SELECT *
FROM CRM_PRODUCTS_PURCHASE
   # Do other joins 
WHERE
    CRM_PRODUCTS_PURCHASE.CONTACTS_ID NOT IN (
        SELECT CONTACTS_ID
        FROM CRM_PRODUCTS_PURCHASE
        WHERE
            CRM_PRODUCTS_PURCHASE.PRODUCTS_ID IN (205, 206))
    AND CRM_PRODUCTS_PURCHASE.PRODUCTS_ID = 204
;

-以上未经测试

注意:子选择中的ORDER BY通常不会起作用。离开ORDER BY直到最后,即mysql - order by inside subquery

在现实世界中,我们经常发现将上述两个查询运行起来要好几个数量级。即生成CONTACTS_ID的列表,并将该值存储在PHP变量中,然后进行第二次查询,以在NOT IN子句中使用这些值。