mysql - 如何在mysql中做一个简单的子查询

标签 mysql subquery

我有一个这样的表模式

mysql> desc material_out;

`enter code here`
+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| id          | int(11)      | NO   |     | 0       |       |
| barcode     | varchar(20)  | NO   |     | NULL    |       |
| name        | varchar(100) | NO   |     | NULL    |       |
| qty         | double       | YES  |     | NULL    |       |
| unit        | varchar(20)  | YES  |     | NULL    |       |
| num_letter  | varchar(30)  | YES  |     | NULL    |       |
| date        | date         | YES  |     | NULL    |       |
| destination | varchar(50)  | YES  |     | NULL    |       |
+-------------+--------------+------+-----+---------+-------+
8 rows in set (0.00 sec)

mysql> desc material_in;

`enter code here`
+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| id          | int(11)      | NO   |     | 0       |       |
| barcode     | varchar(20)  | NO   |     | NULL    |       |
| name        | varchar(100) | NO   |     | NULL    |       |
| qty         | double       | YES  |     | NULL    |       |
| unit        | varchar(20)  | YES  |     | NULL    |       |
| num_letter  | varchar(30)  | YES  |     | NULL    |       |
| date        | date         | YES  |     | NULL    |       |
| destination | varchar(50)  | YES  |     | NULL    |       |
+-------------+--------------+------+-----+---------+-------+
8 rows in set (0.00 sec)

mysql> desc goods;

`enter code here`
+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| id          | int(11)      | NO   |     | 0       |       |
| barcode     | varchar(20)  | NO   |     | NULL    |       |
| name        | varchar(100) | NO   |     | NULL    |       |
| unit        | varchar(20)  | YES  |     | NULL    |       |
| category    | varchar(25)  | YES  |     | NULL    |       |
| first_stok  | double    )  | YES  |     | NULL    |       |
+-------------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

In table material_out I have data of 10,000 rows. and has as many as 350 types of barcodes. In table material_in I have data around 15,000 rows. and has as many as 200 types of barcodes.

but i have a problem when doing a query. takes a long time probably about 3 hours.

I think this is not efficient when you want to print a report.

my query like this.

SELECT br.barcode,
       out.total_out,
       in.total_in,
       out.total_out - in.total_in AS RESULT
FROM
  (SELECT barcode,
          name,
          first_stok,
          unit
   FROM goods
   WHERE category=1) AS br
LEFT JOIN
  (SELECT
     (SELECT sum(qty)
      FROM material_out
      WHERE date >= '2013-08-15'
        AND tanggal <='2013-08-20'
        AND barcode=a.barcode) AS total_out
   FROM material_out a
   GROUP BY a.barcode) AS OUT ON OUT.barcode=br.barcode
LEFT JOIN
  (SELECT
     (SELECT sum(qty)
      FROM material_in
      WHERE date >= '2013-08-15'
        AND tanggal <='2013-08-20'
        AND barcode=a.barcode) AS total_in
   FROM material_in a
   GROUP BY a.barcode) AS IN ON IN.barcode=br.barcode

编辑了兄弟.. 来自 realitygone 的新查询。

<pre>
mysql> SELECT tNEW.barcode,
    ->     tNEW.total_out, tNEW.total_in, tNEW.result,
    ->     tOLD.total_out AS total_out_old, tOLD.total_in AS total_in_old, tNEW.total_in +  tOLD.total_in - tNEW.total_out - tOLD.total_out as sum_total
    -> FROM (
    ->     SELECT goods.barcode,
    ->         SUM(tOUT.qty) AS total_out,
    ->         SUM(tIN.qty) AS total_in,
    ->         SUM(tIN.qty) - SUM(tOUT.qty) AS result
    ->     FROM goods
    ->     LEFT JOIN material_out AS tOUT ON tOUT.barcode=goods.barcode
    ->     LEFT JOIN material_in AS tIN ON tIN.kode=goods.barcode
    ->     WHERE goods.category=1
    ->         AND tOUT.date BETWEEN '2013-05-01' AND '2013-08-31'
    ->         AND tIN.date BETWEEN '2013-05-1' AND '2013-08-31'
    ->     GROUP BY goods.barcode
    -> ) AS tNEW
    -> LEFT JOIN (
    ->     SELECT goods.barcode,
    ->         SUM(tOUT.qty) AS total_out,
    ->         SUM(tIN.qty) AS total_in
    ->     FROM goods
    ->     LEFT JOIN material_out AS tOUT ON tOUT.barcode=goods.barcode
    ->     LEFT JOIN material_in AS tIN ON tIN.kode=goods.barcode
    ->     WHERE goods.category=1
    ->         AND tOUT.date BETWEEN '2013-01-01' AND '2013-04-31'
    ->         AND tIN.date BETWEEN '2013-01-01' AND '2013-04-31'
    ->     GROUP BY goods.barcode
    -> ) AS tOLD ON tOLD.barcode=tNEW.barcode;
+-------------+-----------+----------+------------+---------------+-------------------+--------------------+
|   barcode   | total_out | total_in | result     | total_out_old | total_in_old      | sum_total          |
+-------------+-----------+----------+------------+---------------+-------------------+--------------------+
| CG003       |      2720 |    14400 |      11680 |         17588 |             92160 |              86252 |
| CG009       |       144 |      720 |        576 |          NULL |              NULL |               NULL |
| CG010       |       596 |     1800 |       1204 |          1512 |              6048 |               5740 |
| CG011       |       864 |     4320 |       3456 |          1156 |              3600 |               5900 |
| CG012       |      1875 |     7560 |       5685 |           843 |              4680 |               9522 |
| CG013       |      2520 |     7560 |       5040 |          2826 |             14400 |              16614 |
| CG014       |     19320 |   314340 |     295020 |         39312 |            597312 |             853020 |
| CG015       |       890 |     9750 |       8860 |         12003 |            183330 |             180187 |
| CG017       |        24 |   102000 |     101976 |            26 |               420 |             102370 |
| CG018       |    390000 |   273000 |    -117000 |       1320000 |           1020000 |            -417000 |
| CG020       |       396 |     2170 |       1774 |           820 |              3656 |               4610 |
| CG022       |       238 |     1200 |        962 |           330 |               800 |               1432 |
| CG023       |       752 |     3600 |       2848 |          3585 |             21600 |              20863 |
| CG024       |     21560 |   146068 |     124508 |         64095 | 361552.6000000002 |  421965.6000000002 |
| CG025       |     14833 |    85992 |      71159 |         49049 | 230218.0000000009 | 252328.00000000093 |
| CG026       |       172 |     4000 |       3828 |           766 |              1170 |               4232 |
| CG028       |       126 |     1440 |       1314 |            41 |               660 |               1933 |
| CG029       |        18 |      300 |        282 |            40 |               920 |               1162 |
| CG030       |        50 |      720 |        670 |            50 |               780 |               1400 |
| CHDRY001    |     10260 |    81000 |      70740 |         73440 |            936000 |             933300 |
| CHDRY002    |   4071288 |  3477926 |    -593362 |       9762598 |           8570238 |           -1785722 |
| CHDRY003    |      8880 |     4441 |      -4439 |          NULL |              NULL |               NULL |
| CHDRY004    |     48960 |   238590 |     189630 |        119880 |            413850 |             483600 |
| CHDRY005    |       144 |      144 |          0 |           256 |               256 |                  0 |
| CHDRY006    |     37440 |   211200 |     173760 |        164160 |            968000 |             977600 |
| CHDRY007    |    237600 |  1679040 |    1441440 |        604890 |           4758600 |            5595150 |
| CHDRY009    |    766080 |  2026160 |    1260080 |        698250 |           2151560 |            2713390 |
| CHDRY010    |      3600 |   168000 |     164400 |         40800 |           1488000 |            1611600 |
| CHDRY012    |       200 |     2700 |       2500 |           340 |              5600 |               7760 |
| CHDRY013    |      4290 |    17600 |      13310 |          4290 |             21120 |              30140 |
| CHDRY014    |    278300 |   643720 |     365420 |        466210 |           1243620 |            1142830 |
| CHDRY015    |     78720 |   264100 |     185380 |         81840 |            367070 |             470610 |
| CHDRY018    |   2431270 |  1987260 |    -444010 |       4877450 |           4672689 |            -648771 |
| CHDRY022    |      1320 |     4840 |       3520 |           330 |              1650 |               4840 |
| CHDRY023    |       200 |      110 |        -90 |          NULL |              NULL |               NULL |
| CHDRY024    |      2000 |     4000 |       2000 |           100 |               100 |               2000 |
| CHDRY025    |      1800 |     4000 |       2200 |          NULL |              NULL |               NULL |
| CHDRY026    |       850 |      850 |          0 |          NULL |              NULL |               NULL |
| CHDRY028    |       120 |      480 |        360 |          NULL |              NULL |               NULL |
| CHPRINT001  |      8000 |   222000 |     214000 |         13800 |            390000 |             590200 |
| CHPRINT002  |      4000 |    10000 |       6000 |          4200 |             21000 |              22800 |
| CHPRINT004  |     13600 |   324000 |     310400 |         14400 |            512000 |             808000 |
| CHPRINT005  |     28800 |   136800 |     108000 |         35000 |            133000 |             206000 |
| CHPRINT006  |      3100 |    93000 |      89900 |          5600 |            112000 |             196300 |
| CHPRINT007  |     16800 |    69000 |      52200 |          2000 |              9000 |              59200 |
------------------------------------------------------------------------------------------------------------
</pre>

你好,我有新问题。当我计算字段 tNEW.total_in + tOLD.total_in - tNEW.total_out - tOLD.total_out. 当遇到列包含 null 时,则求和的结果包含 null。 例如在 条码CHDRY025 条码CHDRY003 条码CHDRY028 条码NWDRY004

对于管理员或版主,抱歉,如果我违反了规则。 :-)

====================== 2013 年 9 月 30 日编辑后 ==================== ==================

你好RealityGone, 我使用了您的查询。结果进展顺利。但是当我尝试输入新数据时。然后我重新查询你的显示。但结果与输入的数据不一致。 例如,当我输入您的查询时。结果如下

+----------------------+-----------+----------+------------+---------------+-------------------+
|    barcode           | total_out | total_in | result     | total_out_old | total_in_old      |
+----------------------+-----------+----------+------------+---------------+-------------------+
| TNWET021             |      6195 |    15000 |       8805 |         20085 |             46200 |
| TNWET020             |      3420 |     7650 |       4230 |          4860 |             23925 |
| TNWET019             |      8370 |    25200 |      16830 |         11610 |             47175 |
| TNWET018             |     18690 |    44100 |      25410 |         13800 |             54150 |
| TNWET017             |      1140 |     3750 |       2610 |          3690 |             16200 |
| TNWET016             |     19500 |    56100 |      36600 |         31725 |            111300 |
| TNWET015             |      5145 |    18150 |      13005 |          6510 |             23400 |
| TNWET014             |     33300 |    65250 |      31950 |         96300 |            262500 |
| TNWET013             |      1170 |     5625 |       4455 |          3690 |             13200 |
| TNWET012             |       720 |     2700 |       1980 |          3870 |             13800 |
| TNWET011             |         0 |        0 |          0 |           180 |               450 |
| TNWET010             |         0 |        0 |          0 |           405 |              1125 |
| TNWET009             |         0 |        0 |          0 |             0 |                 0 |



当我进行手动求和并得到这样的结果时。

mysql> select sum(qty) from material_in where barcode='TNWET021' and date BETWEEN '2013-05-01' AND '2013-08-31';
+-------------+
|   sum(qty)  |
+-------------+
|         750 |
+-------------+
1 row in set (0.00 sec)


mysql> select sum(qty) from material_in where barcode='TNWET020' and date BETWEEN '2013-05-01' AND '2013-08-31';
+-------------+
|   sum(qty)  |
+-------------+
|         450 |
+-------------+
1 row in set (0.00 sec)

最佳答案

我认为您的查询甚至没有完成我认为应该做的事情。您没有在问题中指定您期望的输出,但我假设您想要 cargo 表中每个条形码的两个 Material 表中数量字段的 SUM()。 (我还假设“tanggal”字段与其上方的日期字段相同,因为它不在您的 EXPLAIN 输出中,它表示英文日期。)

您当然不需要要连接的表表达式的 SELECT 语句中的子查询。我也不明白为什么这些根本需要是表表达式。我对查询运行得非常慢并不感到惊讶。它是连接表表达式中的相关子查询。

我认为您根本不需要子查询。这是我的简化版本:

SELECT goods.barcode,
    SUM(tOUT.qty) AS total_out,
    SUM(tIN.qty) AS total_in,
    SUM(tOUT.qty)-SUM(tIN.qty) AS result
FROM (

商品 LEFT JOIN material_out AS tOUT ON tOUT.barcode=goods.barcode LEFT JOIN material_in AS tIN ON tIN.barcode=goods.barcode 其中 g.category=1 AND tOUT.date BETWEEN '2013-08-15' AND '2013-08-20' AND tIN.date BETWEEN '2013-08-15' AND '2013-08-20' GROUP BY g.条形码

可能有更好的方法来执行此操作,但这就是我如何像您要求的那样快速将两个日期范围放在一起:

SELECT tNEW.barcode,
    tNEW.total_out, tNEW.total_in,
    tNEW.total_out-tNEW.total_in AS result,
    COALESCE(tOLD.total_out,0) AS total_out_old, COALESCE(tOLD.total_in,0) AS total_in_old
FROM (
    SELECT g.barcode,
        COALESCE(SUM(tOUT.qty),0) AS total_out,
        COALESCE(SUM(tIN.qty),0) AS total_in
    FROM (
        SELECT DISTINCT barcode
        FROM goods
    ) AS g
    LEFT JOIN material_out AS tOUT ON tOUT.barcode=g.barcode
    LEFT JOIN material_in AS tIN ON tIN.barcode=g.barcode
    WHERE g.category=1
        AND tOUT.date BETWEEN '2013-08-15' AND '2013-08-20'
        AND tIN.date BETWEEN '2013-08-15' AND '2013-08-20'
    GROUP BY g.barcode
) AS tNEW
LEFT JOIN (
    SELECT g.barcode,
        SUM(tOUT.qty) AS total_out,
        SUM(tIN.qty) AS total_in
    FROM (
        SELECT DISTINCT barcode
        FROM goods
    ) AS g
    LEFT JOIN material_out AS tOUT ON tOUT.barcode=g.barcode
    LEFT JOIN material_in AS tIN ON tIN.barcode=g.barcode
    WHERE g.category=1
        AND tOUT.date BETWEEN '2013-01-01' AND '2013-04-31'
        AND tIN.date BETWEEN '2013-01-01' AND '2013-04-31'
    GROUP BY g.barcode
) AS tOLD ON tOLD.barcode=tNEW.barcode

关于mysql - 如何在mysql中做一个简单的子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18996445/

相关文章:

带有子查询的 MySQL 查询花费的时间比应该的长

php - 使用 php 中的下拉选项过滤数据以显示

php - 上传到 mysql 时来自 excel 的日期发生变化

mysql - "The total number of locks exceeds the lock table size"删除267条记录

php - 按其他表的结果排序

sql - BigQuery SQL 错误 : Name rank not found inside latest at [9:15]

sql - 子查询 - 如何引用外部查询值

mysql - 如何在子查询或分组依据上获取多列

mysql - 从另一个带有内部的表中计数

php - MySQL查找第一列的字符串,回显第二列的字符串