Php 来自多个表的MySQL在“on子句”中左连接未知列

Php 来自多个表的MySQL在“on子句”中左连接未知列,php,mysql,silverstripe,Php,Mysql,Silverstripe,我有一个有趣的问题,我似乎很难回答 我需要从多个表中选择数据,并连接到另一个表中,该表中的列可能不在其他表中 我试过几个角度。这是第一个: SELECT SiteTree.*, Page.*, AlbumItem.*, Album.* FROM SiteTree, AlbumItem, Album LEFT JOIN Page ON SiteTree.ID = Page.ID 在“on子句”中抛出:1054-未知列“SiteTree.ID”,可能是因为当从相册表中选择时尝试加入时,没有Site

我有一个有趣的问题,我似乎很难回答

我需要从多个表中选择数据,并连接到另一个表中,该表中的列可能不在其他表中

我试过几个角度。这是第一个:

SELECT SiteTree.*, Page.*, AlbumItem.*, Album.*
FROM SiteTree, AlbumItem, Album
LEFT JOIN Page ON SiteTree.ID = Page.ID
在“on子句”中抛出:1054-未知列“SiteTree.ID”,可能是因为当从相册表中选择时尝试加入时,没有SiteTree.ID列

我也试过:

SELECT SiteTree.*, Page.*, AlbumItem.*, Album.*
FROM SiteTree LEFT JOIN Page ON SiteTree.ID = Page.ID, AlbumItem, Album
它返回大约20行,我知道基于where子句应该只有2行。实际上,每个结果行大约有10个副本

其中条款如下:

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
我需要知道的是,我尝试做的事情是否可以不借助联合?

SiteTree表中是否有一个名为ID的列?给出错误消息后,没有。修复此问题,使其引用表中实际存在的列


还有,你为什么要做ANSI连接,即使用。。。你应该是内部连接,否则你将无法得到你所期望的。

AlbumItem和Album缺乏实际的连接标准,这导致了两个完整的外部连接/交叉连接问题。你应该把这两个表正确地连接起来。否则,每个表至少会有一条记录。

好的,我现在有一个有效的查询

为了正确地看待问题,我在SilverStripe中构建了一个可标记的模块。SilverStripe中的ORM允许将扩展添加到多个数据对象上,这些数据对象可能具有不共享公共列的唯一表集,以执行与on子句的联接

在生成查询时,我试图克服SQLQuery对象的限制。SilverStripe中的SQLQuery对象不支持UNION,因此我希望不必生成完整的原始SQL查询。似乎没有联合就无法避免笛卡尔乘积的产生

因此,我最终为PDO制作了一个薄包装,并使用了一个基于联合的查询,如下所示。它是在一个脚本中自动生成的,该脚本遍历对象图以查找所有相关的表,因此它比我手动编写时要稍微详细一些。它还应该使用正则表达式匹配,以便匹配更准确,但此时我更关心的是查询生成一些可用的输出:

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

SiteTree表中是否有名为ID的列?有。还有,你为什么要做ANSI连接,即使用。。。您应该是内部连接,否则您将无法获得您所期望的。从SiteTree.ID=Page.ID内部加入相册项目内部加入相册产生的结果与从SiteTree.ID=Page.ID,相册项目,相册上的SiteTree左侧加入页面产生的结果相同。您应该始终加入某些内容。不要让交叉连接来代替你。你能展示一下你的表结构吗?不幸的是,没有什么可以加入相册或相册项,也就是说,它们与SiteTree表不共享任何公用键。其目的更多的是尝试在不进行联合的情况下,跨多个表对给定键的存在进行单个查询。我知道,正在创建各种组合的笛卡尔积-是否有可以控制的方法,或者我最好使用联合?如果它们与查询中的任何内容都不相关,那么它们就不属于查询。。。如果您需要这些信息,我会添加第二个查询,或者加入一个联合。。。但是,即使使用UNION,您也在组合两个不同的记录集,这意味着不同的事情。阅读本文可以解释为什么我从SiteTree.ID=Page.ID、AlbumItem、Album上的SiteTree LEFT JOIN页面获得20个from子句结果。现在的问题似乎是如何过滤笛卡尔积,为每个匹配生成一个组合行