0

我需要在一个垂直表中展平 2 行(然后加入第三个表),我通常通过为我需要的每个字段制作一个派生表来做到这一点。只有两个字段,我认为这并没有那么不合理。

但我知道我想要在派生表中返回的行是我与第三个表连接的子集。所以我试图找出最好的派生表,以便查询最有效地运行。

我认为派生表的 where 子句越严格,派生表越小,得到的响应就越好。

我真正想要的是将派生表的 where 子句与第三个表的连接相关联,但你不能在 sql 中这样做,这太糟糕了。但是我不是sql大师,也许有一些我不知道的技巧。

另一种选择是制作没有 where 子句的派生表,它最终会加入整个表两次(每个字段一次),当我对它们进行加入时,加入会过滤掉所有内容。

所以我真正要问的是什么是制作派生表的最佳方法,我非常清楚我想要什么行,但 sql 不会让我得到它们。

一个例子:

table1
------

id  tag     value
--  -----   -----
1   first   john
1   last    smith
2   first   sally
2   last    smithers


table2
------

id     occupation
--     ----------
1      carpenter
2      homemaker


select table2.occupation, firsttable.first, lasttable.last from
table2, (select value as first from table1 where tag = 'first') firsttable,
(select value as last from table1 where tag = 'last') lasttable
where table2.id = firsttable.id and table2.id = lasttable.id

我想要做的是制作 firsttable where 子句 where tag='first' and id = table2.id

4

3 回答 3

1

DERIVED 表不会像您期望的那样存储中间结果。这些只是使代码更简单的一种方法。使用派生表并不意味着派生表表达式将首先执行,其输出将用于与剩余的表连接。在大多数情况下,优化器会自动取消派生表。

但是,在某些情况下,优化器可能希望存储子查询的结果,从而实现材料化而不是展平。这通常发生在您有某种聚合函数或类似的情况时。但在您的情况下,查询过于简单,因此优化器将展平查询

此外,存储派生表表达式不会使您的查询变得更快,反而会使情况变得更糟。您真正的问题是规范化过多。修复该查询只是两个表的连接。

为什么要进行这种规范化?为什么要将 col 值存储为行。尝试对 table1 进行非规范化,使其具有第一和最后两列。这将是最好的解决方案。

另外,您在 id 和 tag 列上有适当的索引吗?如果是,那么合并连接非常适合您的查询。

请提供这些表的索引详细信息以及您的查询生成的计划。

您的查询将像内部联接查询一样使用。

select table2.occupation, first.valkue as first, last.value as last 
from 
table2
inner join table1  first 
on first.tag = 'first'
and first.id =table2.id
inner join table1 last
on last.tag = 'last'
and table2.id = last.id 
于 2012-07-23T13:45:37.733 回答
0

我想你要的是一个COMMON TABLE EXPRESSION. 如果您的平台没有实现它们,那么临时表可能是最好的选择。

于 2012-07-23T12:46:14.040 回答
0

我有点困惑。您的查询看起来不错。. . 尽管使用正确的连接语法看起来更好。

select table2.occupation, firsttable.first, lasttable.last
from table2 join
       (select value as first from table1 where tag = 'first') firsttable
       on table2.id = firsttable.id join
       (select value as last from table1 where tag = 'last') lasttable
       on table2.id = lasttable.id 

此查询执行您要求它执行的操作。SQL 是一种声明性语言,而不是过程性语言。这意味着您描述结果集并依赖数据库 SQL 编译器将其转换为正确的命令集。(也就是说,有时查询的结构确实会使某些引擎更容易或更难生成有效的查询计划。)

于 2012-07-23T13:09:56.063 回答