将子查询转换为MySQL的JOIN语句?

将子查询转换为MySQL的JOIN语句?,mysql,sql,Mysql,Sql,以下是我当前的查询: SELECT prod.id, prod.title, prod.price, prod.status, (SELECT COUNT(*) FROM payments WHERE product = prod.id AND ( vendor = '1' AND credited = 'Vendor' )

以下是我当前的查询:

 SELECT prod.id,
       prod.title,
       prod.price,
       prod.status,
       (SELECT COUNT(*)
        FROM   payments
        WHERE  product = prod.id
               AND ( vendor = '1'
                     AND credited = 'Vendor' )
               AND ( status = 'Completed'
                      OR status = 'Pending'
                      OR status = 'Canceled_Reversal' )) AS sales,
       (SELECT SUM(price)
        FROM   payments
        WHERE  product = prod.id
               AND ( vendor = '1'
                     AND credited = 'Vendor' )
               AND ( status = 'Completed'
                      OR status = 'Pending'
                      OR status = 'Canceled_Reversal' )) AS revenue
FROM   products prod
WHERE  member = '1'
       AND status != 'Deleted' 
       AND status != 'Blocked'  
现在我在主查询中使用了两个子查询

有没有办法改用JOIN语句或简化查询以加快查询速度


还是没有什么能让它快得多?

我会写得简单一点:

SELECT p.id, p.title, p.price, p.status,
       (SELECT COUNT(*)
        FROM payments pa
        WHERE pa.product = p.id AND
              pa.vendor = p.member AND
              pa.credited = 'Vendor' AND
              pa.status IN ('Completed','Pending', 'Canceled_Reversal')
      ) AS sales,
       (SELECT SUM(pa.price)
        FROM payments pa
        WHERE pa.product = p.id AND
              pa.vendor = p.member AND
              pa.credited = 'Vendor' AND
              pa.status IN ('Completed','Pending','Canceled_Reversal')
      ) AS revenue
FROM products p
WHERE p.member = 1 AND
      p.status NOT IN ('Deleted', 'Blocked');
这基本上是您的查询,具有更简单的别名和逻辑

使用
付款(产品、供应商、信用、状态、价格)
索引,这可能比其他方法更快

另一种选择是:

SELECT p.id, p.title, p.price, p.status,
       COUNT(pa.product) as sales
       SUM(pa.price) as revenue
FROM products p LEFT JOIN
     payments pa
     ON pa.product = p.id AND
        pa.vendor = p.member AND
        pa.credited = 'Vendor' AND
        pa.status IN ('Completed', 'Pending', 'Canceled_Reversal')
WHERE p.member = 1 AND
      p.status NOT IN ('Deleted', 'Blocked')
GROUP BY p.id, p.title, p.price, p.status;

但是,子查询可能会更快。

将连接与聚合一起使用:

SELECT
    prod.id,
    prod.title,
    prod.price,
    prod.status,
    COALESCE(t.sales, 0) AS sales,
    COALESCE(t.revenue, 0) AS revenue
FROM products prod
LEFT JOIN
(
    SELECT
        product,
        COUNT(*) AS sales,
        SUM(price) AS revenue
    FROM payments p
    WHERE vendor = '1' AND credited = 'Vendor' AND
          status IN ('Completed', 'Pending', 'Canceled_Reversal')
    GROUP BY product
) t
    ON t.product = prod.id;
请注意,我们在这里使用左连接,以满足
产品
表中的某些产品在
付款
表中甚至可能没有任何匹配数据的可能性。在这种情况下,我们还使用
COALESCE
报告销售额和收入的零值

上述别名为
t
的子查询可能可以使用以下索引进行优化:

payments (product, vendor, credit, status, price)

谢谢,效果很好!子查询通常比连接更快吗?@ShadowAccount。有时候,没有硬性规定。真正的比较是聚合,避免外部聚合通常有利于性能。