如何在不使用UNION ALL的情况下简化查询?

时间:2015-03-27 02:41:15

标签: mysql

SELECT i.id invn_id, IF(ss.serial_id IS NOT NULL, ss.serial_id, NULL) serial_number,
        IF(ss.serial_id IS NOT NULL, 1.000000, -(i.qty)) qty,
        'auto' flag, i.sid site_id, i.prod_id, i.fifo_total_amount, i.trans_date
 FROM inventories i
 INNER JOIN prod p ON p.id = i.prod_id
 LEFT JOIN sale_products sp ON sp.inventory_id = i.id
 LEFT JOIN sale_serial ss ON ss.prod_id = i.prod_id AND ss.sale_id = sp.sale_id
 WHERE i.qty < 0 
        AND ('2015-03-25 00:00:00' IS NULL OR i.trans_date >= '2015-03-25 00:00:00') 
        AND ('2015-03-27 08:27:36' IS NULL OR i.trans_date <= '2015-03-27 08:27:36') 
        AND p.name NOT IN ('Starting Balance' , 'Opening Balance', 'Equity')
        AND i.prod_id = 7655 AND (0 = 0 OR i.sid = 0)
 UNION ALL 
 (
 SELECT i.id invn_id, 
        IF(ss.serial_id IS NOT NULL,ss.serial_id, NULL) serial_number, 
         -(SUM(IF(ss.serial_id IS NOT NULL, 1.000000, -(i.qty))) - -(i.qty)) qty, -- difference
        'auto' flag, i.sid site_id, i.prod_id, i.fifo_total_amount, i.trans_date
 FROM inventories i
 INNER JOIN prod p ON p.id = i.prod_id
 LEFT JOIN sale_products sp ON sp.inventory_id = i.id
 LEFT JOIN sale_serial ss ON ss.prod_id = i.prod_id AND ss.sale_id = sp.sale_id
 WHERE i.qty < 0
        AND ('2015-03-25 00:00:00' IS NULL OR i.trans_date >= '2015-03-25 00:00:00')
        AND ('2015-03-27 08:27:36' IS NULL OR i.trans_date <= '2015-03-27 08:27:36')
        AND p.name NOT IN ('Starting Balance' , 'Opening Balance', 'Equity')
        AND i.prod_id = 7655 AND (0 = 0 OR i.sid = 0)
 GROUP BY i.id -- difference
 HAVING qty > 0 -- difference
 ) 
 ORDER BY site_id , prod_id , trans_date , qty ASC

观察第二个语句(联合表)与第一个语句几乎相同,但注释中的行除外。我对结果感到满意,但由于其冗余而对查询不满意。是否有可能将此简短?

我想得到的输出是这样的,例如:

我的总数量为5,ID为95514:

 +-------+-----------+---------+
 | id    | qty       | prod_id |
 +-------+-----------+---------+
 | 95514 | 5.000000  |    7655 |
 +-------+-----------+---------+

如果我执行上述查询,结果将如下:

+---------+---------------+----------+------+---------+---------+-------------------+---------------------+
| invn_id | serial_number | qty      | flag | site_id | prod_id | fifo_total_amount | trans_date          |
+---------+---------------+----------+------+---------+---------+-------------------+---------------------+
|   95514 | 237658        | 1.000000 | auto |       1 |    7655 |         2763.0194 | 2010-07-22 09:48:24 |
|   95514 | 237671        | 1.000000 | auto |       1 |    7655 |         2763.0194 | 2010-07-22 09:48:24 |
|   95514 | 237699        | 1.000000 | auto |       1 |    7655 |         2763.0194 | 2010-07-22 09:48:24 |
|   95514 | 237658        | 2.000000 | auto |       1 |    7655 |         2763.0194 | 2010-07-22 09:48:24 |
+---------+---------------+----------+------+---------+---------+-------------------+---------------------+

前三行在UNION ALL中返回查询的第一个语句,而第四行返回第二个语句。如果我们总结qty列,我们可以得到值5.

1 个答案:

答案 0 :(得分:0)

我怀疑你想要group by with rollup

SELECT i.id invn_id, 
        IF(ss.serial_id IS NOT NULL,ss.serial_id, NULL) serial_number, 
         -(SUM(IF(ss.serial_id IS NOT NULL, 1.000000, -(i.qty))) - -(i.qty)) qty, -- difference
        'auto' flag, i.sid site_id, i.prod_id, i.fifo_total_amount, i.trans_date
 FROM inventories i
 INNER JOIN prod p ON p.id = i.prod_id
 LEFT JOIN sale_products sp ON sp.inventory_id = i.id
 LEFT JOIN sale_serial ss ON ss.prod_id = i.prod_id AND ss.sale_id = sp.sale_id
 WHERE i.qty < 0
        AND ('2015-03-25 00:00:00' IS NULL OR i.trans_date >= '2015-03-25 00:00:00')
        AND ('2015-03-27 08:27:36' IS NULL OR i.trans_date <= '2015-03-27 08:27:36')
        AND p.name NOT IN ('Starting Balance' , 'Opening Balance', 'Equity')
        AND i.prod_id = 7655 AND (0 = 0 OR i.sid = 0)
 GROUP BY i.id WITH ROLLUP
 HAVING qty > 0 -- difference

但是,我并非100%确定这是如何符合SELECT逻辑的。