带有JOIN,COUNT和GROUP BY的MYSQL SELECT

时间:2019-08-14 11:45:53

标签: mysql join group-by count

我更改了mysql结构,并在过去使用 SUM CASE 列keyindex进行了此查询:

SELECT 
    orders.id,
    orders.tool_id,
    date(orders.date_placement) AS cdate,
    CAST(orders.date_placement AS DATE) AS lala,
    positions.id,
    positions.optionindex,
    positions.keyindex,
    tools.id,
    tools.tool_name,
    tools.tool_number,
    SUM(CASE WHEN keyindex=1 THEN 1 ELSE 0 END) AS value1,
    SUM(CASE WHEN keyindex=2 THEN 1 ELSE 0 END) AS value2,
    SUM(CASE WHEN keyindex=3 THEN 1 ELSE 0 END) AS value3,
    SUM(CASE WHEN keyindex=4 THEN 1 ELSE 0 END) AS value4,
    DATE_FORMAT(orders.date_placement, '%Y-%m')  AS nicecdate
 FROM orders
 LEFT JOIN tools  
    ON  tools.id=orders.tool_id
 LEFT JOIN positions
    ON positions.order_id=orders.id
 WHERE
    tools.id = ? 
 group by DATE_FORMAT(orders.date_placement, '%Y-%m')

此查询的结果如下:

ID | value1   | value2  | value3  | nicedate  
1  |    1     |  1      |    4    |  2018-09
2  |    0     |  0      |    1    |  2018-10
3  |    1     |  1      |    1    |  2018-11
4  |    2     |  0      |    0    |  2018-12   

在前端创建一些堆积图是很好的选择。

但是现在我添加了一个具有映射值(ID1 = value1,ID2 = value2,....)的附加表(repkey),并在其中的第一个表 keyindex2 中添加了新列除了keyindex。

ID | keyindex1 | keyindex2 | created 
1  |    1      |  27       | 2019-01
2  |    1      |  27       | 2019-01
3  |    2      |  25       | 2019-02
4  |    1      |  27       | 2019-03
5  |    10     |  27       | 2019-04

结果是,我需要根据对应的月份从keyindex和keyindex2中获得每个组合:

ID | keyindex1 | keyindex2 | Value           |count |created 
1  |    1      |  27       | value1 value27  |  2   |2019-01
2  |    2      |  25       | value2 value25  |  1   |2019-02
3  |    1      |  27       | value1 value27  |  1   |2019-03
4  |    10     |  27       | value10 value27 |  1   |2019-04

这是我尝试过的方法,但我不知道如何计算对应月份的keyindex和keyindex2 的组合。结果也与旧结构的结果不同,因此我完全不确定此查询是否完全符合我的要求。

 SELECT
            orders.id,
            orders.tool_id,
            date(orders.date_placement) AS cdate,
            CAST(orders.date_placement AS DATE) AS lala,
            positions_list.id AS POSITIONID,
            positions_list.order_id AS POSITIONORDERID,
            positions_list.keyindex,
            positions_list.keyindex2,
            RepK.keynr,
            RepK.content AS repcontent,
            RepK.p_company,
            RepK2.keynr,
            RepK2.content AS repcontent2,
            RepK2.p_company,
            COUNT(positions_list.keyindex) AS count,
            COUNT(positions_list.keyindex2) AS count2,
            DATE_FORMAT(orders.date_placement, '%Y-%m') AS nicecdate
      from orders
      JOIN tools
            ON tools.id=orders.tool_id
      JOIN positions_list 
            ON positions_list.order_id = orders.id
      JOIN repkey as RepK
            ON   RepK.keynr=positions_list.keyindex
            AND  RepK.p_company=orders.comp_id
      JOIN repkey AS RepK2
            ON RepK2.keynr=positions_list.keyindex2
      WHERE
            tools.id =:id
      group by DATE_FORMAT(orders.date_placement, '%Y-%m')

顺便说一句:此查询非常慢(超过10秒)。 Web服务器/数据库位于带有ssd的nginx上,因此问题必须在我的查询中。是JOINS的原因吗?

1 个答案:

答案 0 :(得分:1)

当您的需求变化太大,以致查询的输出和结构不再相同时,最好与现有代码保持一定距离,并从头开始思考。

您的需求是计算相应月份的keyindex和keyindex2的组合

我们不知道您的数据库,但是这个简单的需求提示强烈支持采用如下所示的解决方案:

SELECT
        positions_list.keyindex,
        positions_list.keyindex2,
        DATE_FORMAT(orders.date_placement, '%Y-%m') AS nicedate,
        COUNT(*) as count,
        --...more columns
      from orders
      JOIN tools
            ON tools.id=orders.tool_id
      JOIN positions_list 
            ON positions_list.order_id = orders.id
      JOIN repkey as RepK
            ON   RepK.keynr=positions_list.keyindex
            AND  RepK.p_company=orders.comp_id
      JOIN repkey AS RepK2
            ON RepK2.keynr=positions_list.keyindex2
      WHERE
            tools.id =:id
      group by DATE_FORMAT(orders.date_placement, '%Y-%m'),positions_list.keyindex,positions_list.keyindex2

将要计数的列放在GROUP中,它应该可以解决问题。现在,根据您的表关系和要计数的内容,COUNT可能需要做一些工作(例如,如果要计算不同的订单,则可能需要使用COUNT(DISTINCT orders.id)),但是您需要要点。

另外,请花一些时间来确保在每个表之间充分使用JOIN(=INNER JOIN) and LEFT JOIN,它将帮助您获得所需的结果。

关于性能,是的,JOIN会影响您的查询时间,但是要帮助您,我们需要另一个主题和您的数据库详细信息(最重要的是:索引!您已经可以自己检查它) 。还有一个dedicated SE site for DBA