如何从以下查询中优化或删除冗余

Posted

技术标签:

【中文标题】如何从以下查询中优化或删除冗余【英文标题】:How to optimize or remove redundancy from following query 【发布时间】:2010-01-26 22:58:30 【问题描述】:

我有 4 张桌子

Table1 (employee)
id          name
--------------------
1           a
2           b

Table2 (appointment)
id    table1id    table3id    table4id   sdate    edate     typeid
-----------------------------------------------------------------------------------
1       1              1          1      1/1/09    NULL       100
2       2              2          1      1/1/09    NULL       101


Table3 (title)
id      name
---------------
1       worker1
2       worker2
3       Assistant
4       Manager

Table4 (Department names)
id      name
-------------------
1       Logistics
2       ABC
3       XYZ

Type
id       name
----------------
100      w (primary)
101      e (secondary)
102      r (other-primary)
103      t (.....)
104      y (....)

为了避免重复,我将查询写成

Select id, name, title, dept
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1id
INNER JOIN table3 c ON b.table3id = c.id
INNER JOIN table4 d ON d.id = b.table4id
WHERE typeid =
        (
           SELECT min(type_id) /* i want primary type appointments */
           FROM table2
           WHERE sdate < getdate() and (edate > getdate() or edate IS NULL)
           AND sdate = (select max(sdate) from table2 where table1id = a.id)
           AND typeid in (100, 102)
        )
AND b.sdate < getdate() and (b.edate > getdate() or b.edate IS NULL)
AND b.sdate = (select max(sdate) from table2 where table1id = a.id)

/* last two i have to repeat again to remove dupes */

有没有一种方法可以减少两次使用相同条件并查询它只指定一次或任何其他更好的方法? AND 输入 (100, 102)

【问题讨论】:

Grrr... 你已经定义了表别名,但你不要在 JOIN 语法之外使用它们 如果您能说明您要回答的问题,那将有所帮助。 如果您使用真实的表名和列名而不是 INNER JOIN table4 d ON d.id = b.table4id 之类的名称,则更容易理解您的查询。你能解释一下你的查询应该做什么吗? 我正在尝试以积极就业和主要就业类型返回员工。每个员工可以有2-3个工种,可以有多个头衔(晋升时可以过期)所以我想要最新的记录。 【参考方案1】:

在联接中使用子查询来获取您想要的数字,这样的事情会有所改进吗?

Select id, name, title, dept
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1id
INNER JOIN table3 c ON b.table3id = c.id
INNER JOIN table4 d ON d.id = b.table4id
INNER JOIN (select max(sdate) from table2 group by table1id) new1 ON new1.table1id = a.id
WHERE typeid =
    (
       SELECT min(type_id) /* i want primary type appointments */
       FROM table2
       WHERE sdate < getdate() and (edate > getdate() or edate IS NULL)
       AND sdate = (select max(sdate) from table2 where table1id = a.id)
       AND typeid in (100, 102)
    )
AND b.sdate < getdate() and (b.edate > getdate() or b.edate IS NULL)
AND b.sdate = new1.sdate

您也可以尝试查看 GROUP BY 的 HAVING 子句。我认为您可以执行以下操作:

Select id, name, title, dept
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1id
INNER JOIN table3 c ON b.table3id = c.id
INNER JOIN table4 d ON d.id = b.table4id
WHERE b.sdate < getdate() and (b.edate > getdate() or b.edate IS NULL)
AND typeid in (100, 102)
GROUP BY id, name, title, dept
HAVING b.sdate = max(sdate)
  AND typeid = min(type_id)

但是,以上可能会拉取整个列表的最小值和最大值,而不是每个 a.id。我忘记了您是否可以在 max 中使用分区来指定要最大化的内容,或者我是否正在考虑那里的 Oracle。如果没有,您始终可以使用子查询来获取每个 a.id 的最佳条目。

【讨论】:

【参考方案2】:

我使用了相同的查询,它运行得很快,我没有找到任何其他方法来优化它

【讨论】:

以上是关于如何从以下查询中优化或删除冗余的主要内容,如果未能解决你的问题,请参考以下文章

怎样优化数据库查询

如何优化或加速以下 sql 查询?

一条sql执行过长的时间,你如何优化,从哪些方面?

07-leveldb查询性能优化方法

如何做SqlServer 数据查询优化!

mysql-冗余和重复索引