首页 文章

坚持使用mysql嵌套的select语句

提问于
浏览
0

我有三个表,我加入了一个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

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

我想制作一个select语句,选择购买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

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

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

相关问题