MySQL查询难度

时间:2017-03-09 16:58:15

标签: mysql select

我希望您提供以下帮助:

查询1:

SELECT stock.ST_CODE as xCODE, (sum(ordercont.QTY) / 12) as x12WeeksAvg
FROM orders
LEFT JOIN ordercont ON ordercont.O_REF = orders.O_REF
LEFT JOIN stock ON stock.PD_CODE = ordercont.PD_CODE
WHERE stock.ST_CODE IS NOT NULL
  AND orders.O_CUSTDATE BETWEEN DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 84 DAY)
  AND DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)
GROUP BY stock.ST_CODE

查询2:

SELECT stock.ST_CODE as xCODE, (sum(ordercont.QTY) / 4) as x4WeeksAvg
FROM orders LEFT JOIN ordercont ON ordercont.O_REF = orders.O_REF
LEFT JOIN stock ON stock.PD_CODE = ordercont.PD_CODE
WHERE stock.ST_CODE IS NOT NULL
  AND orders.O_CUSTDATE BETWEEN DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 28 DAY)
  AND DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)
GROUP BY stock.ST_CODE

有没有办法得到这样的结果(查询返回不同数量的结果):

------------------------------------
| xCode | x12WeeksAvg | x4WeeksAvg |
------------------------------------
|  ...  |     ...     |    ...     |
------------------------------------

谢谢!

2 个答案:

答案 0 :(得分:1)

拆分BETWEEN条件

orders.O_CUSTDATE BETWEEN DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 84 DAY) 
                      AND DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)

分为两部分

AND orders.O_CUSTDATE >= DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 84 DAY) 
AND orders.O_CUSTDATE <= DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)

并将其重写为

AND orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 84) DAY
AND orders.O_CUSTDATE <= CURDATE() - INTERVAL (DAYOFWEEK(NOW()) - 1) DAY

获得更短,更易读的代码。对第二个查询执行相同的操作。

现在两个查询只有两个表达式不同

(sum(ordercont.QTY) / 12) as x12WeeksAvg
(sum(ordercont.QTY) /  4) as x4WeeksAvg

orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 84) DAY
orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 28) DAY

给出

<X>: orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 84) DAY

<Y>: orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 28) DAY

您可以使用条件聚合来组合两个查询:

SELECT stock.ST_CODE as xCODE,
    (sum(CASE WHEN <X> THEN ordercont.QTY ELSE 0 END) / 12) as x12WeeksAvg,
    (sum(CASE WHEN <Y> THEN ordercont.QTY ELSE 0 END) /  4) as x4WeeksAvg
FROM orders
LEFT JOIN ordercont ON ordercont.O_REF = orders.O_REF
LEFT JOIN stock     ON stock.PD_CODE   = ordercont.PD_CODE
WHERE stock.ST_CODE IS NOT NULL
  AND orders.O_CUSTDATE <= CURDATE() - INTERVAL (DAYOFWEEK(NOW()) - 1) DAY
GROUP BY stock.ST_CODE

相应地替换<X><Y>

<强>更新

要提高性能,您可以添加

AND orders.O_CUSTDATE >= CURDATE() - INTERVAL (WEEKDAY(NOW()) + 84) DAY

到WHERE子句。

另请注意,条件stock.ST_CODE IS NOT NULL会将LEFT JOIN转换为INNER JOIN。所以你也可以写JOIN

答案 1 :(得分:0)

您可以像这样对它们进行子查询以获得所需的输出:

SELECT A.xCODE, 
    COALESCE(B.x12WeeksAvg, 'N/A') as x12WeeksAvg, 
    COALESCE(C.x4WeeksAvg, 'N/A') as x4WeeksAvg
FROM (SELECT DISTINCT ST_CODE as xCODE FROM stock) A
LEFT JOIN (
    SELECT stock.ST_CODE as xCODE, (sum(ordercont.QTY) / 12) as x12WeeksAvg
    FROM orders
      LEFT JOIN ordercont ON ordercont.O_REF = orders.O_REF
      LEFT JOIN stock ON stock.PD_CODE = ordercont.PD_CODE
    WHERE stock.ST_CODE IS NOT NULL
      AND orders.O_CUSTDATE BETWEEN DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 84 DAY) AND DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)
    GROUP BY stock.ST_CODE
          ) B ON A.xCODE = B.xCODE
LEFT JOIN (
    SELECT stock.ST_CODE as xCODE, (sum(ordercont.QTY) / 4) as x4WeeksAvg
    FROM orders
      LEFT JOIN ordercont ON ordercont.O_REF = orders.O_REF
      LEFT JOIN stock ON stock.PD_CODE = ordercont.PD_CODE
    WHERE stock.ST_CODE IS NOT NULL
      AND orders.O_CUSTDATE BETWEEN DATE_SUB( (DATE_ADD(CURDATE(), INTERVAL - WEEKDAY(CURDATE()) DAY)) , INTERVAL 28 DAY) AND DATE_SUB(DATE(NOW()), INTERVAL DAYOFWEEK(NOW())-1 DAY)
    GROUP BY stock.ST_CODE
          ) C ON A.xCODE = C.xCODE
WHERE COALESCE(B.x12WeeksAvg, C.x4WeeksAvg) IS NOT NULL