连接语法中的MySQL相关子查询
我希望通过指定innertable.id=outertable.id,在内部查询上提供WHERE条件。然而,MySQL(5.0.45)报告“where子句”中的未知列'outertable.id'。这种类型的查询可能吗 内部查询使用GROUPBY将行旋转到列。这可以完全在外部查询中执行,但由于额外的连接,可能会产生额外的开销 或者,我可以在内部查询中取消WHERE条件,而是指定一个ON outertable.id=innerquery.id,但它会获取整个内部查询行集以再次连接外部查询,这是低效的 实际SQL如下所示:连接语法中的MySQL相关子查询,sql,mysql,join,subquery,entity-attribute-value,Sql,Mysql,Join,Subquery,Entity Attribute Value,我希望通过指定innertable.id=outertable.id,在内部查询上提供WHERE条件。然而,MySQL(5.0.45)报告“where子句”中的未知列'outertable.id'。这种类型的查询可能吗 内部查询使用GROUPBY将行旋转到列。这可以完全在外部查询中执行,但由于额外的连接,可能会产生额外的开销 或者,我可以在内部查询中取消WHERE条件,而是指定一个ON outertable.id=innerquery.id,但它会获取整个内部查询行集以再次连接外部查询,这是低效
select t.ticketid, u.userid, t.fullname, u.loginapi_userid, t.email, tp.subject, tp.contents, a.PhoneNumber, a.Location, a.Extension, a.BusinessUnit, a.Department
from swtickets t
inner join swticketposts tp on t.ticketid = tp.ticketid
inner join swusers u on t.userid = u.userid
left join
(
select
cfv.typeid,
min(case cfv.customfieldid when 1 then cfv.fieldvalue end) as 'PhoneNumber',
min(case cfv.customfieldid when 3 then cfv.fieldvalue end) as 'Location',
min(case cfv.customfieldid when 5 then cfv.fieldvalue end) as 'Extension',
min(case cfv.customfieldid when 8 then cfv.fieldvalue end) as 'BusinessUnit',
min(case cfv.customfieldid when 9 then cfv.fieldvalue end) as 'Department'
from swcustomfieldvalues cfv
where cfv.typeid = t.ticketid
group by cfv.typeid
) as a on 1 = 1
where t.ticketid = 2458;
我的建议将是你以效率为由排除的。例如,省略where子句并使用联接(根据t.ticketid=a.ticketid)
你是否能够通过一些具体的例子来证明你对效率低下的看法?我知道你在说什么,但不管你使用什么方法,外部查询中的每一行都会连接到内部查询中的每一行,因此根据执行计划,它可能不会像你想象的那样效率低下?我想问题是'cfv.typeid=t.ticketid'?我的想法是,虽然MySQL支持相关子查询,但您尝试做的事情似乎可能会在连接中失败,因为“内部”查询与WHERE子句中的查询不同,并不是真正的“内部”查询。但是看起来您可以将where子句从子查询中取出,并在a.typeid=t.ticketid上设置联接条件。我将使用多个联接编写它。当你说它“可能会招致额外的开销”时,这就告诉我你还没有测试过它。如果您有合适的索引,那么连接应该非常简单
这还显示了通用的“保留所有内容”表设计模式的一个缺陷。您使用的是实体属性值设计,如果您试图生成传统的结果集,则最终无法使其可伸缩。不要在一个查询中尝试这样做 而是首先查询规范化表:
SELECT t.ticketid, u.userid, t.fullname, u.loginapi_userid, t.email,
tp.subject, tp.contents
FROM swtickets t
INNER JOIN swticketposts tp ON (t.ticketid = tp.ticketid)
INNER JOIN swusers u ON (t.userid = u.userid)
WHERE t.ticketid = 2458;
然后查询自定义字段,结果显示在结果集的多行上:
SELECT cfv.customfieldid, cfv.fieldvalue
FROM swcustomfieldvalues cfv
WHERE cfv.typeid = 2458;
结果集中有多行,每个自定义字段对应一行:
+---------------+--------------+
| customfieldid | fieldvalue |
+---------------+--------------+
| 1 | 415-555-1234 |
| 3 | Third office |
| 5 | 123 |
| 8 | Support |
| 9 | Engineering |
+---------------+--------------+
然后,您需要编写应用程序代码,将结果集字段映射到循环中的应用程序对象字段
以这种方式使用实体属性值表在性能和代码维护方面都更具可扩展性。您的问题的答案是否定的,您不可能像现在这样引用相关名称。派生表由内部查询在外部查询开始计算联接之前生成。因此,像
t
、tp
和u
这样的相关名称对内部查询不可用
为了解决这个问题,我建议在内部查询中使用相同的常量整数值,然后在外部查询中使用实条件而不是1=1
连接派生表
SELECT t.ticketid, u.userid, t.fullname, u.loginapi_userid, t.email,
tp.subject, tp.contents, a.PhoneNumber, a.Location, a.Extension,
a.BusinessUnit, a.Department
FROM swtickets t
INNER JOIN swticketposts tp ON (t.ticketid = tp.ticketid)
INNER JOIN swusers u ON (t.userid = u.userid)
LEFT OUTER JOIN (
SELECT cfv.typeid,
MIN(CASE cfv.customfieldid WHEN 1 THEN cfv.fieldvalue END) AS 'PhoneNumber',
MIN(CASE cfv.customfieldid WHEN 3 THEN cfv.fieldvalue END) AS 'Location',
MIN(CASE cfv.customfieldid WHEN 5 THEN cfv.fieldvalue END) AS 'Extension',
MIN(CASE cfv.customfieldid WHEN 8 THEN cfv.fieldvalue END) AS 'BusinessUnit',
MIN(CASE cfv.customfieldid WHEN 9 THEN cfv.fieldvalue END) AS 'Department'
FROM swcustomfieldvalues cfv
WHERE cfv.typeid = 2458
GROUP BY cfv.typeid
) AS a ON (a.typeid = t.ticketid)
WHERE t.ticketid = 2458;
很抱歉,这是查询的另一个变体的剩余内容。这与产生的实际错误无关,因此我已将其从上述问题中删除。该设计称为实体属性值。它以多种方式破坏了规范化,而且使用起来非常困难。在内部查询(cfv)中使用“WHERE cfv.typeid=2458”会导致对cfv进行讨厌的表扫描,这是因为缺少索引。然而,忽略此条件会使情况更糟,导致“使用临时;使用文件排序”除了对派生查询进行额外的表扫描之外,我不确定“内部查询”是什么意思。将有5个新的内部连接,所以可能这就是你的意思。我希望您的CFV表在typeid上有一个索引。我可能会按照这个顺序在typeid和customfieldid上建立一个聚集索引;相反,它依赖于数据库之外的代码来执行透视。在EAV的情况下,无法在一个查询中提高效率。您应该在应用程序代码中进行透视。我最初的问题是,“这种类型的查询可能吗?”(与MySQL 5.0相关)。更改模式或对应用程序代码进行修改超出了问题主题的范围。