我想通过指定innertable.id = outertable.id为内部查询提供WHERE条件。但是,MySQL(5.0.45)在'where子句'中报告“未知列'outertable.id'”。这种查询是否可行?
内部查询使用GROUP BY将行旋转到列。这可以完全在外部查询中执行,但由于额外的连接可能会产生额外的开销。
或者,我可以在内部查询中省略WHERE条件,而是指定一个ON outertable.id = innerquery.id,但它会获取整个内部查询行集再次连接外部,这是低效的。
实际的SQL显示在下面:
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;
答案 0 :(得分:30)
您的问题的答案是否定的,不可能像您一样引用相关名称。在外部查询开始评估联接之前,派生表由内部查询生成。因此,内部查询无法使用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;
答案 1 :(得分:2)
您正在使用实体 - 属性 - 值设计,如果您尝试生成传统结果集,最终无法实现此可伸缩性。不要尝试在一个查询中执行此操作。
相反,首先查询规范化表:
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 |
+---------------+--------------+
然后,您需要编写应用程序代码,以便在循环中将结果集字段映射到应用程序对象字段。
以这种方式使用Entity-Attribute-Value表在性能和代码维护方面更具可扩展性。
答案 2 :(得分:1)
我会用多个连接来编写它。当你说它“可能会产生额外的开销”时,它会告诉我你没有对它进行测试以确定。如果你有合适的索引,那么连接应该是非常简单的。
这也只显示了通用“保持一切”表设计模式的一个缺陷。
答案 3 :(得分:0)
我的建议是你在效率方面排除的。例如。省略where子句并使用连接(根据t.ticketid = a.ticketid)
您是否能够通过一些具体的例子证明您对低效率的看法?我知道你在说什么,但无论你使用什么方法,外部查询中的每一行都被连接到内部查询中的每一行,所以根据执行计划,它可能不像你怀疑的那样低效?
答案 4 :(得分:0)
我想问题是'cfv.typeid = t.ticketid'呢?我的想法是,虽然MySQL支持相关的子查询,但你想要做的似乎是它可能在连接中失败,因为'内部'查询实际上不在查询的其余部分内部,就像它是在WHERE子句中。但看起来您可以从子查询中取出where子句,并在a.typeid = t.ticketid上创建连接条件。