stuck-on-mysql嵌套select语句

sc4hvdpw  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(263)

我在select语句中加入了三个表:
表crm\U联系人结构:

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

表crm\U产品结构:

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

表crm\产品\采购:

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

因此,客户当然可以购买多种产品。
我想做一个select语句,选择购买产品\u id 204(免费样本)的所有客户,但如果他们购买了产品\u type=monthly\u subscription的产品,我不想在结果中包含这些客户
所以我期望的输出是联系人的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)
xdyibdwo

xdyibdwo1#

您应该尽可能避免嵌套的子选择,因为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子查询
在我们的实际案例中,我们经常发现将上面的查询作为两个查询运行要好几个数量级。i、 e.生成一个联系人id列表并将该值存储在一个php变量中,然后在notin子句中使用这些值进行第二次查询。

1mrurvl1

1mrurvl12#

首先你提到 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)

相关问题