这个查询可以做什么样的查询优化?

时间:2021-04-07 11:20:05

标签: mysql sql

我将根据此查询列出订单数据。此查询基本上从表中提取重复订单数据。我还使用了一些下拉菜单和输入字段来搜索/过滤查询结果。

SELECT
    orders.id,
    parent_id,
    (
    SELECT
        COUNT(*)
    FROM
        orders o
    WHERE
        o.parent_id = orders.id
) AS recurring_order_count,
shopify_order_type,
shopify_order_id,
shopify_order_customer_ID,
coupon_code AS coupon,
FORMAT(shopify_order_total_price, 2) AS shopify_order_total_price,
FORMAT(
    shopify_order_subtotal_price,
    2
) AS shopify_order_subtotal_price,
FORMAT(
    shopify_order_total_line_items_price,
    2
) AS shopify_order_total_line_items_price,
FORMAT(commission_amount, 2) AS commission_amount,
(
    CASE WHEN is_paid = 0 THEN 'No' WHEN is_paid = 1 THEN 'Yes' ELSE 'Rejected'
END
) AS is_paid,
(
    CASE WHEN is_invoice_generated = 1 THEN 'Pending' ELSE 'Invoice Generated'
END
) AS is_invoice_generated,
DATE_FORMAT(
    shopify_order_created_at,
    '%m-%d-%Y'
) AS shopify_order_created_at,
(
    CASE WHEN is_paused = 0 THEN 'Running' ELSE 'Paused'
END
) AS is_paused,
DATE_FORMAT(
    shopify_recurring_date,
    '%m-%d-%Y'
) AS shopify_recurring_date
FROM
    `orders`
WHERE
    coupon_code LIKE '%GERALD8314%' OR shopify_order_id LIKE '%GERALD8314%' OR(
        CASE WHEN is_paid = 0 THEN 'No' WHEN is_paid = 1 THEN 'Yes' ELSE 'Rejected'
    END
) LIKE '%GERALD8314%' OR(
    CASE WHEN is_invoice_generated = 1 THEN 'Pending' ELSE 'Invoice Generated'
END
) LIKE '%GERALD8314%' OR DATE_FORMAT(
    shopify_order_created_at,
    '%m-%d-%Y'
) LIKE '%GERALD8314%' OR(
    CASE WHEN is_paused = 0 THEN 'Running' ELSE 'Paused'
END
) LIKE '%GERALD8314%' OR DATE_FORMAT(
    shopify_recurring_date,
    '%m-%d-%Y'
) LIKE '%GERALD8314%' AND DATE_FORMAT(
    shopify_order_created_at,
    '%Y-%m-%d'
) BETWEEN ? AND ?
GROUP BY
    `id`
HAVING
    parent_id = 0 AND shopify_order_type = 1
ORDER BY
    `id`
DESC
LIMIT 10 OFFSET 0

此查询是否已优化?就查询执行速度而言,此 SELECT COUNT(*) FROM orders WHERE o.parent_id = orders.id AS recurring_order_count 行是最昂贵的吗?有什么我应该注意提高查询速度的吗?请指教。

1 个答案:

答案 0 :(得分:0)

ORLIKE 带前导通配符对性能来说很糟糕。考虑在相关列中使用 FULLTEXT 索引。如果实用,速度会快很多。

    WHERE  coupon_code LIKE '%GERALD8314%'
      OR  shopify_order_id LIKE '%GERALD8314%' OR( CASE WHEN is_paid = 0 THEN 'No' WHEN is_paid = 1 THEN 'Yes' ELSE 'Rejected' END ) LIKE '%GERALD8314%' OR( CASE WHEN is_invoice_generated = 1 THEN 'Pending' ELSE 'Invoice Generated' END ) LIKE '%GERALD8314%'
      OR  DATE_FORMAT( shopify_order_created_at, '%m-%d-%Y' ) LIKE '%GERALD8314%' OR( CASE WHEN is_paused = 0 THEN 'Running' ELSE 'Paused' END ) LIKE '%GERALD8314%'
      OR  DATE_FORMAT( shopify_recurring_date, '%m-%d-%Y' ) LIKE '%GERALD8314%'
      AND  DATE_FORMAT( shopify_order_created_at, '%Y-%m-%d' ) BETWEEN ? AND ?

另外,结果可能会有惊喜。请注意,您有

a OR b OR c AND d

相同
a OR b OR (c AND d)

我怀疑你想要

(a OR b OR c) AND d

我认为 GROUP BY 是不必要的。并且 HAVING 子句可以合并到 WHERE 中。

    GROUP BY  `id`
    HAVING  parent_id = 0
      AND  shopify_order_type = 1
    ORDER BY  `id` DESC

这有多个问题:

DATE_FORMAT( shopify_order_created_at, '%Y-%m-%d' ) BETWEEN ? AND ?

BETWEEN 是“包容性的”。根据您编写查询的方式,它将包括整个结束的。这可能不是您想要的。

假设变量是DATE或者DATETIME,可以简化为

shopify_order_created_at BETWEEN ? AND ?

可能还有更多提示;解决这些问题,然后回来了解更多。