MySQL Must Know 13: Temporary Table - Save Intermediate Results

The reading is compiled from "MySQL Must Know and Know" - Zhu Xiaofeng . For details, please log in to the purchase column on the official website of Geek Time .

Temporary tables

When encountering some complex queries, it is often impossible to complete the query in one step, or the query statement will be too complex, and the cost of development and maintenance will be too high. At this time, you can use a temporary table.

A temporary table is a special table used to store intermediate results of a query and is automatically deleted when the current connection ends.

There are two types of temporary tables in MySQL, namely internal temporary tables and external temporary tables:

  • The internal temporary table is mainly used for performance optimization, which is automatically generated by the system and we cannot see it;
  • The external temporary table is created by SQL statement, we can use;

Create a temporary table:

create temporary table 表名
(
字段名 字段类型,
...
);

Compared with ordinary tables, temporary tables have 3 different characteristics:

  • The syntax for creating a temporary table requires the keyword temporary;
  • After the temporary table is created, only the current connection is visible, and other connections are invisible, with connection isolation;
  • The temporary table will be automatically deleted after the current connection ends;

Because temporary tables have connection isolation, different connections create temporary tables with the same name without conflicts, which is suitable for running concurrent programs. Moreover, after the connection ends, the temporary table will be automatically deleted, and there is no need to worry about a large amount of useless intermediate data remaining in the database. Therefore, these characteristics can be used to store the intermediate results of SQL queries with temporary tables.


Optimize complex queries

Requirements: Supermarket operators want to query the sales quantity, purchase quantity, and return quantity of some specific commodities in December 2020. Then, we must first calculate the three modules of sales, purchase, and return separately, and use a temporary table to The results of intermediate calculations are stored, and finally merged together to form the result set desired by the supermarket operator.

data preparation:

mysql> select * from demo.transactiondetails;
+---------------+------------+----------+-------+------------+----------+
| transactionid | itemnumber | quantity | price | salesvalue | discount |
+---------------+------------+----------+-------+------------+----------+
|             1 |          1 |        2 | 89.00 |     176.22 |     0.99 |
|             1 |          2 |        5 |  5.00 |      24.75 |     0.99 |
|             2 |          1 |        3 | 89.00 |     234.96 |     0.88 |
+---------------+------------+----------+-------+------------+----------+

mysql> select * from demo.importhead;
+------------+------------+---------+------------+---------------------+
| listnumber | supplierid | stockid | operatorid | confirmationdate    |
+------------+------------+---------+------------+---------------------+
| 4587       |          1 |       1 |          1 | 2020-12-02 00:00:00 |
| 4588       |          2 |       1 |          1 | 2020-12-03 00:00:00 |
+------------+------------+---------+------------+---------------------+

mysql> select * from demo.importdetails;
+------------+------------+----------+-------------+-------------+
| listnumber | itemnumber | quantity | importprice | importvalue |
+------------+------------+----------+-------------+-------------+
| 4587       |          1 |        2 |          55 |         110 |
| 4587       |          2 |        5 |           3 |          15 |
| 4587       |          3 |        8 |           5 |          40 |
| 4588       |          1 |        3 |          60 |         180 |
+------------+------------+----------+-------------+-------------+

mysql> select * from demo.returnhead;
+------------+------------+---------+------------+---------------------+
| listnumber | supplierid | stockid | operatorid | confirmationdate    |
+------------+------------+---------+------------+---------------------+
| 654        |          1 |       1 |          1 | 2020-12-02 00:00:00 |
| 655        |          2 |       1 |          1 | 2020-12-03 00:00:00 |
+------------+------------+---------+------------+---------------------+

mysql> select * from demo.returndetails;
+------------+------------+----------+-------------+-------------+
| listnumber | itemnumber | quantity | returnprice | returnvalue |
+------------+------------+----------+-------------+-------------+
| 654        |          1 |        1 |          55 |          55 |
| 654        |          2 |        1 |           3 |           3 |
| 655        |          3 |        1 |           5 |           5 |
| 655        |          1 |        1 |          60 |          60 |
+------------+------------+----------+-------------+-------------+

mysql> select * from demo.goodsmaster;
+------------+---------+-----------+---------------+------+-----------+
| itemnumber | barcode | goodsname | specification | unit | saleprice |
+------------+---------+-----------+---------------+------+-----------+
|          1 | 0001    || 16||     89.00 |
|          2 | 0002    || NULL          ||      5.00 |
+------------+---------+-----------+---------------+------+-----------+

Query transactiondetailsthe sales quantity and sales amount of each single product, and store them in the temporary table:

mysql> create temporary table demo.tempsales
    -> select itemnumber, sum(quantity) as quantity, sum(salesvalue) as salesvalue
    -> from demo.transactiondetails
    -> group by itemnumber
    -> order by itemnumber;
Query OK, 2 rows affected (0.03 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from demo.tempsales;
+------------+----------+------------+
| itemnumber | quantity | salesvalue |
+------------+----------+------------+
|          1 |        6 |     495.73 |
|          2 |       21 |      98.65 |
+------------+----------+------------+

Query importheadpurchase data and save it in a temporary table:

mysql> create temporary table demo.tempimport
    -> select b.itemnumber, sum(b.quantity) as quantity, sum(b.importvalue) as importvalue
    -> from demo.importhead a
    -> join demo.importdetails b
    -> on (a.listnumber = b.listnumber)
    -> group by b.itemnumber;
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from demo.tempimport;
+------------+----------+-------------+
| itemnumber | quantity | importvalue |
+------------+----------+-------------+
|          1 |        5 |         290 |
|          2 |        5 |          15 |
|          3 |        8 |          40 |
+------------+----------+-------------+

Calculate the return information returndetailsand save it in a temporary table:

mysql> create temporary table demo.tempreturn
    -> select b.itemnumber, sum(b.quantity) as quantity, sum(b.returnvalue) as returnvalue
    -> from demo.returnhead a
    -> join demo.returndetails b on (a.listnumber=b.listnumber)
    -> group by b.itemnumber;
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from demo.tempreturn;
+------------+----------+-------------+
| itemnumber | quantity | returnvalue |
+------------+----------+-------------+
|          1 |        2 |         115 |
|          2 |        1 |           3 |
|          3 |        1 |           5 |
+------------+----------+-------------+

Now, the sales information, purchase information and return information of a single product can be aggregated together.

Introduce product information table. Because the product information table contains all products, placing the product information table on the left and performing left joins with other tables can ensure that all products are included in the result set. All non-existing values ​​are set to 0, and then filtered to remove the products whose sales, purchases, and returns are all 0, so that we can get the final query results we want: the number of product sales in December 2020, Purchase quantity and return quantity.

select a.itemnumber, a.goodsname, 
ifnull(b.quantity, 0) as salesquantity, 
ifnull(c.quantity, 0) as importquantity,
ifnull(d.quantity, 0) as returnquantity
from demo.goodsmaster as a
left join demo.tempsales as b on (a.itemnumber = b.itemnumber)
left join demo.tempimport as c on (a.itemnumber = c.itemnumber)
left join demo.tempreturn as d on (a.itemnumber = d.itemnumber)
having salesquantity>0 or importquantity>0 or returnquantity>0; -- 在结果集中剔除没有销售,没有进货,也没有返厂的商品
+------------+-----------+---------------+----------------+----------------+
| itemnumber | goodsname | salesquantity | importquantity | returnquantity |
+------------+-----------+---------------+----------------+----------------+
|          1 ||             6 |              5 |              2 |
|          2 ||            21 |              5 |              1 |
+------------+-----------+---------------+----------------+----------------+

In short, through the temporary table, a complex problem can be split into many related steps, and the intermediate running results can be stored for subsequent queries. In this way, the set-oriented SQL query is turned into a process-oriented programming mode, which greatly reduces the difficulty.


Temporary tables in memory and temporary tables on disk

Due to different storage methods, temporary tables can also be divided into memory temporary tables and disk temporary tables , which have their own advantages and disadvantages.

One thing to note about in-memory temporary tables is that you can tell MySQL to store temporary tables in memory by specifying the engine type (such as engine=memory).

When creating a temporary table on the disk, as long as the storage engine is not specified, MySQL will default the storage engine to InnoDB and store the table on the disk.

Create an in-memory temporary table:

mysql> create tempory table demo.mytrans_memory
-> (
-> itemnumber int,
-> groupnumber int,
-> branchnumber int
-> ) engin = memory;  -- 临时表数据存在内存中
Query OK, 0 rows affected (0.00 sec)

Create a temporary table with the same structure on disk:

mysql> create temporary table demo.mytrans_disk
-> (
-> itemnumber int,
-> groupnumber int,
-> branchnumber int
-> );
Query OK, 0 rows affected (0.00 sec)

Insert the same number of records into both tables, and then do a query separately:

mysql> select count(*) from demo.mytrans_memory;
+----------+
| count(*) |
+----------+
| 4355 |
+----------+
1 row in set (0.00 sec)
 
mysql> select count(*) from demo.mytrans_disk;
+----------+
| count(*) |
+----------+
| 4355 |
+----------+
1 row in set (0.21 sec)

Clearly, in-memory temporary table queries are faster.

type advantage shortcoming
in-memory temporary table query speed Once the power is cut off, all data will be lost and the data cannot be retrieved
disk temporary table Data is not easy to lose relatively slow

Of course, temporary tables also have disadvantages, such as occupying space. When using temporary tables, comprehensive consideration should be given to simplifying queries and occupying resources. It should neither overburden the system, but also simplify queries to the greatest extent by storing intermediate results.


need:

There is such a sales flow meter, assuming that there are multiple stores, each store has multiple cash registers, and each cash register sells a variety of commodities, how to query the sales amount of each store and each cash register accounted for What about the ratio of the sales amount of the store it belongs to?

mysql> select * from demo.task_sales;
+--------------+---------------+------------+------------+
| branchnumber | cashiernumber | itemnumber | salesvalue |
+--------------+---------------+------------+------------+
|            1 |             1 |          1 |         10 |
|            1 |             2 |          3 |         20 |
|            2 |             1 |          1 |         30 |
|            2 |             2 |          2 |         40 |
+--------------+---------------+------------+------------+
  1. Calculating Total Store Sales

    mysql> create temporary table demo.temp_branch
        -> select branchnumber, sum(salesvalue) as salesvalue
        -> from demo.task_sales
        -> group by branchnumber;
    Query OK, 2 rows affected (0.01 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    
    mysql> select * from demo.temp_branch;
    +--------------+------------+
    | branchnumber | salesvalue |
    +--------------+------------+
    |            1 |         30 |
    |            2 |         70 |
    +--------------+------------+
    
  2. According to stores and cash registers, calculate the total

    mysql> create temporary table demo.temp_cashier
        -> select branchnumber, cashiernumber, sum(salesvalue) as salesvalue
        -> from demo.task_sales
        -> group by branchnumber, cashiernumber;
    Query OK, 4 rows affected (0.01 sec)
    Records: 4  Duplicates: 0  Warnings: 0
    
    mysql> select * from demo.temp_cashier;
    +--------------+---------------+------------+
    | branchnumber | cashiernumber | salesvalue |
    +--------------+---------------+------------+
    |            1 |             1 |         10 |
    |            1 |             2 |         20 |
    |            2 |             1 |         30 |
    |            2 |             2 |         40 |
    +--------------+---------------+------------+
    
  3. According to the sales ratio of stores and cash registers

    mysql> select a.branchnumber, a.cashiernumber, a.salesvalue/b.salesvalue
        -> from demo.temp_cashier as a, demo.temp_branch as b
        -> where (a.branchnumber = b.branchnumber)
        -> order by a.branchnumber, a.cashiernumber;
    +--------------+---------------+---------------------------+
    | branchnumber | cashiernumber | a.salesvalue/b.salesvalue |
    +--------------+---------------+---------------------------+
    |            1 |             1 |                    0.3333 |
    |            1 |             2 |                    0.6667 |
    |            2 |             1 |                    0.4286 |
    |            2 |             2 |                    0.5714 |
    +--------------+---------------+---------------------------+
    4 rows in set (0.00 sec)
    

Guess you like

Origin blog.csdn.net/qq_31362767/article/details/123603051