【问题标题】:MySQL FROM multiple tables LEFT JOIN Unknown column in 'on clause'MySQL FROM 多个表 LEFT JOIN 'on 子句'中的未知列
【发布时间】:2012-06-09 05:17:32
【问题描述】:

我有一个有趣的查询,我似乎遇到了麻烦。

我需要从多个表中选择数据并加入另一个表,该表的列可能不存在于其他表中。

我已经尝试了几个角度。这是第一个:

SELECT SiteTree.*, Page.*, AlbumItem.*, Album.*
FROM SiteTree, AlbumItem, Album
LEFT JOIN Page ON SiteTree.ID = Page.ID

抛出此问题:#1054 - 'on Clause' 中的未知列 'SiteTree.ID',大概是因为当它从 Album 表中选择时尝试加入时,没有 SiteTree.ID 列。

我也试过这个:

SELECT SiteTree.*, Page.*, AlbumItem.*, Album.*
FROM SiteTree LEFT JOIN Page ON SiteTree.ID = Page.ID, AlbumItem, Album

返回大约 20 行,我知道根据 where 子句应该只有 2 行。事实上,每个结果行大约有 10 个副本

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

我需要知道的是,如果不求助于工会,我正在尝试做的事情是否可行?

【问题讨论】:

  • 阅读此 link 解释了为什么我的 from 子句 FROM SiteTree LEFT JOIN Page ON SiteTree.ID = Page.ID, AlbumItem , Album 得到 20 个结果。现在的问题似乎是如何将笛卡尔积过滤到为每个匹配生成一个组合行

标签: php mysql silverstripe


【解决方案1】:

AlbumItemAlbum 缺乏实际的连接标准会导致(一对)完全外部连接/交叉连接问题。您应该正确加入这两个表。否则,您将至少获得每个表的一条记录。

【讨论】:

    【解决方案2】:

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

    为了正确看待事物,我在 SilverStripe 中构建了一个可标记模块。 SilverStripe 中的 ORM 允许将扩展添加到多个 DataObjects,这些 DataObjects 可能具有不共享公共列的唯一表集,以执行带有 ON 子句的 JOIN

    在生成查询时,我试图在 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
    

    【讨论】:

      【解决方案3】:

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

      另外,你为什么要ANSI JOINs(即使用,)...你应该是INNER JOINs,否则你不会得到你所期望的。

      【讨论】:

      • SiteTree 表中是否有名为 ID 的列? 是的。 另外,你为什么要使用 ANSI JOIN(即使用 ,)...你应该是 INNER JOIN,否则你不会得到你期望的结果。 FROM SiteTree LEFT JOIN Page ON SiteTree.ID = Page.ID INNER JOIN AlbumItem INNER JOIN Album 产生与 @987654326 相同的结果@
      • 你应该总是加入ON的东西。不要留给CROSS JOIN 为您填写。能否请您展示您的表格结构。
      • 不幸的是,没有什么可以加入 AlbumAlbumItem,即它们不与 SiteTree 表共享任何公共密钥。目的更多是尝试在不进行联合的情况下尝试对多个表中给定键的存在进行单个查询。我知道, 正在创建各种组合的笛卡尔积 - 有没有可以控制的地方或者我最好使用联合?
      • 如果它们与查询中的任何内容都不相关,那么它们不属于查询...如果您需要该信息,我会在第二个查询中添加它,或者UNION ...但即使使用UNION,您也将两个不同的记录集组合在一起,这意味着不同的事情。
      猜你喜欢
      • 1970-01-01
      • 2012-02-04
      • 2021-09-29
      • 1970-01-01
      • 2011-05-03
      • 1970-01-01
      • 1970-01-01
      • 2014-05-25
      • 2014-03-13
      相关资源
      最近更新 更多