我有一个有趣的查询,我似乎遇到了麻烦。
我需要从多个表中选择数据并加入另一个表,该表的列可能不存在于其他表中。
我已经尝试了几个角度。这是第一个:
SELECT SiteTree.*, Page.*, AlbumItem.*, Album.*
FROM SiteTree, AlbumItem, Album
LEFT JOIN Page ON SiteTree.ID = Page.ID
抛出这个:#1054 - 'on子句'中的未知列'SiteTree.ID',可能是因为当从Album表中选择时尝试加入时没有SiteTree.ID列。
我也试过这个:
SELECT SiteTree.*, Page.*, AlbumItem.*, Album.*
FROM SiteTree LEFT JOIN Page ON SiteTree.ID = Page.ID, AlbumItem, Album
返回约20行,我知道应该只有2基于where子句。事实上,每个结果行大约有10个副本
where where子句如下:
WHERE (
(
AlbumItem.ClassName = 'AlbumItem' OR
Album.ClassName = 'Album' OR
SiteTree.ClassName = 'Page' OR
SiteTree.ClassName = 'HomePage' OR
SiteTree.ClassName = 'NewsCategory' OR
SiteTree.ClassName = 'NewsArticle' OR
SiteTree.ClassName = 'CartPage' OR
SiteTree.ClassName = 'Product' OR
SiteTree.ClassName = 'ProductGroup' OR
SiteTree.ClassName = 'MemberProfilePage' OR
SiteTree.ClassName = 'SubscriptionPage' OR
SiteTree.ClassName = 'ErrorPage' OR
SiteTree.ClassName = 'RedirectorPage' OR
SiteTree.ClassName = 'VirtualPage' OR
SiteTree.ClassName = 'UserDefinedForm' OR
SiteTree.ClassName = 'CheckoutPage' OR
SiteTree.ClassName = 'OrderConfirmationPage' OR
SiteTree.ClassName = 'TagPage'
) AND (
INSTR(Page.Tags,'x') OR
INSTR(AlbumItem.Tags,'x') OR
INSTR(Album.Tags,'x')
)
)
将查询减少到这会产生正确的结果,但它也不适用于其他表:
SELECT SiteTree.*, Page.*
FROM SiteTree
LEFT JOIN Page ON SiteTree.ID = Page.ID
我需要知道的是,如果我不想诉诸工会,我想做什么呢?
答案 0 :(得分:1)
AlbumItem
和Album
缺少实际的加入条件会导致(偶数)完全外部加入/交叉加入问题。您应该正确加入这两个表。否则,您将为每个表格获得至少一条记录。
答案 1 :(得分:1)
好的,我现在有一个有效的查询。
为了正确看待我,我正在SilverStripe中构建一个可标记的模块。 SilverStripe中的ORM允许将扩展添加到多个DataObject,这些DataObject可能具有唯一的表集,这些表不共享公共列以执行带有JOIN
子句的ON
。
在尝试生成查询时,我试图使用SQLQuery
对象的限制。 SilverStripe中的SQLQuery对象不支持UNION
所以我希望我不必生成完整的原始SQL查询。似乎没有办法避免使用UNION
来避免产生笛卡尔积。
所以我最终为PDO制作了一个瘦包装器,并使用基于UNION
的查询,如下所示。它是在脚本中自动生成的,该脚本遍历对象图以查找所有相关表,因此它比我手动编写时更加冗长。此外,它应该使用正则表达式匹配,因此匹配更准确,但在这个时间点我更关心查询产生一些可用的输出:
SELECT SQL_CALC_FOUND_ROWS SiteTree.ClassName, SiteTree.ID
FROM SiteTree LEFT JOIN Page ON SiteTree.ID = Page.ID
WHERE (
SiteTree.ClassName = 'Page' OR
SiteTree.ClassName = 'HomePage' OR
SiteTree.ClassName = 'NewsCategory' OR
SiteTree.ClassName = 'NewsArticle' OR
SiteTree.ClassName = 'GalleryPage' OR
SiteTree.ClassName = 'CartPage' OR
SiteTree.ClassName = 'Product' OR
SiteTree.ClassName = 'ProductGroup' OR
SiteTree.ClassName = 'MemberProfilePage' OR
SiteTree.ClassName = 'SubscriptionPage' OR
SiteTree.ClassName = 'ErrorPage' OR
SiteTree.ClassName = 'RedirectorPage' OR
SiteTree.ClassName = 'VirtualPage' OR
SiteTree.ClassName = 'UserDefinedForm' OR
SiteTree.ClassName = 'CheckoutPage' OR
SiteTree.ClassName = 'OrderConfirmationPage' OR
SiteTree.ClassName = 'TagPage'
) AND (
INSTR(Page.Tags,'x')
)
UNION ALL
SELECT AlbumItem.ClassName, AlbumItem.ID
FROM AlbumItem
WHERE (AlbumItem.ClassName = 'AlbumItem') AND (INSTR(AlbumItem.Tags,'x'))
UNION ALL
SELECT Album.ClassName, Album.ID
FROM Album
WHERE (Album.ClassName = 'Album') AND (INSTR(Album.Tags,'x'))
LIMIT 0,40
答案 2 :(得分:0)
ID
表中是否有一个名为SiteTree
的列?鉴于错误消息,没有。修复此问题,以便您引用表中实际存在的列。
另外,你为什么要做ANSI JOIN
(即使用,...)......你应该INNER JOIN
,因为否则你将得不到你所期望的。