2

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

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

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

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

抛出这个:#1054 - 'on 子句'中的未知列 '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子句如下:

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

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

4

3 回答 3

1

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

于 2012-06-08T03:08:31.217 回答
1

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

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

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
于 2012-06-08T21:17:32.037 回答
0

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

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

于 2012-06-08T02:58:41.903 回答