mysql - 优化Mysql查询,同时连接同一个表多次

标签 mysql sql

Can anybody help me optimize this mysql query?
The query is taking more than 1 min to fetch 1000 rows of data. 
The sub query with FIND_IN_SET(id,GROUP_CONCAT(t.id))!=0 in the select statement is taking too much time to fetch data.

此外,您能否提供可用于优化我们必须多次连接同一个表的查询的提示。 查询如下:

   SELECT mem.id,
    CASE 
    WHEN t.due_date IS NOT NULL THEN
    (SELECT description FROM descriptionTable WHERE CODE=
    (SELECT task_type FROM memberTask WHERE FIND_IN_SET(id,GROUP_CONCAT(t.id))!=0 AND due_date=MIN(t.due_date) LIMIT 1))
    ELSE
    (SELECT description FROM descriptionTable WHERE CODE=
    (SELECT task_type FROM memberTask WHERE FIND_IN_SET(id,GROUP_CONCAT(t1.id))!=0 AND due_date=MIN(t1.due_date) LIMIT 1))
    END AS task_type
    FROM member mem
    INNER JOIN memberProgram p ON mem.id=p.member_id
    LEFT JOIN memberTask t ON t.program=p.prog_name AND t.member_id=p.member_id AND t.status=1
    LEFT JOIN memberTask t1 ON t1.member_id=p.member_id AND t1.status=1 AND t1.program IS NULL 
    GROUP BY mem.id

提前致谢!!!

最佳答案

您使用查询的方式将增加查询执行的复杂性,并且必须经过大量交叉连接的行才能提取所需的行。更好的解决方案将首先从目标表 memberTask 中提取所需的行,然后将其连接到主查询。

SELECT 
REPLACE(GROUP_CONCAT(COALESCE(CASE WHEN t1.program IS NOT NULL THEN t1.id ELSE NULL END,'')),',','') AS first_dueDate,
REPLACE(GROUP_CONCAT(COALESCE(CASE WHEN t1.program IS NOT NULL THEN 'first' ELSE 'second' END,'')),',','') AS selectFlag,
REPLACE(GROUP_CONCAT(COALESCE(CASE WHEN t1.program IS NULL THEN t1.id ELSE NULL END,'')),',','') AS first_dueDate,
aa.member_id FROM memberTask t1
INNER JOIN (SELECT due_date,program,aa.member_id,MAX(tsk.id) AS selId FROM memberTask tsk 
INNER JOIN ( SELECT t.member_id,t.program,t.task_type,MIN(due_date) AS seldate FROM memberTask t WHERE tsk.status=1 
GROUP BY t.member_id,IFNULL(t.program,''))aa 
ON tsk.member_id=aa.member_id AND IFNULL(tsk.program,'')=IFNULL(aa.program,'') AND tsk.due_date=aa.seldate 
GROUP BY due_date,program,aa.member_id) bb ON t1.id=bb.selId GROUP BY t1.member_id,t1.program

查询的分割如下:

SELECT t.member_id,t.program,t.task_type,MIN(due_date) AS seldate FROM memberTask t WHERE tsk.status=1 
GROUP BY t.member_id,IFNULL(t.program,'')

这是最里面的查询,它将根据memberid及其选择最短截止日期的程序提取记录。

SELECT due_date,program,aa.member_id,MAX(tsk.id) AS selId FROM memberTask tsk 
INNER JOIN (Inner Most Query)aa 
ON tsk.member_id=aa.member_id AND IFNULL(tsk.program,'')=IFNULL(aa.program,'') AND tsk.due_date=aa.seldate 
GROUP BY due_date,program,aa.member_id

此查询将提取具有相同截止日期的行中的最大 ID

SELECT 
REPLACE(GROUP_CONCAT(COALESCE(CASE WHEN t1.program IS NOT NULL THEN t1.id ELSE NULL END,'')),',','') AS first_dueDate,
REPLACE(GROUP_CONCAT(COALESCE(CASE WHEN t1.program IS NOT NULL THEN 'first' ELSE 'second' END,'')),',','') AS selectFlag,
REPLACE(GROUP_CONCAT(COALESCE(CASE WHEN t1.program IS NULL THEN t1.id ELSE NULL END,'')),',','') AS first_dueDate,
aa.member_id FROM memberTask t1
INNER JOIN (second query) bb ON t1.id=bb.selId GROUP BY t1.member_id,t1.program

这会将整个多行数据拉至单行。

现在,在将所选数据加入到主查询时,您应该使用以下情况。

SELECT * FROM member mem
INNER JOIN program pro om mem.id=pro.member_id
LEFT JOIN tmpTable tl ON t1.member_id=mem.member_id AND
CASE WHEN FIND_IN_SET(pro.`prog_name`, t1.prog_relate_task) THEN t1.program=pro.program AND t1.selectFlag='first'
ELSE t1.selectFlag='second' END 

这些是对您的案例的一般理解。您可以根据需要更改拉取记录

让我知道它是否有效?

关于mysql - 优化Mysql查询,同时连接同一个表多次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46951405/

相关文章:

mysql - SQL如何选择两个日期之间的日期和月份

php - Mysql 使用 JOIN 时为每个表设置不同的选择集

php - 如何检查给定日期是否存在于表中?

PHP/MySQL - 在数据库中存储数组

c# - 所有实体类型的关键属性必须映射到存储函数返回的相同的不可空列

sql - 是否有任何纯 sql 方法可以通过以下方式从日志表中删除数据

java - JPA中的事务实现

mysql - Sails js 从数据库中获取数据而模型中没有模式定义

Python:将大型 SQL Server 查询结果导出到 .txt 文件

sql - 将表数据从一个 SQL Server 导出到另一台 SQL Server