【问题标题】:Combine Multiple MySQL Queries on the Same Table Into One将同一张表上的多个 MySQL 查询合并为一个
【发布时间】:2015-06-05 10:01:11
【问题描述】:

如何在同一张表上进行多个查询,选择不同的列?

如果它有帮助...所有查询在 SQL 语句的选择部分都有一个公共列。他们都选择ID,然后选择特定的内容。

因此,每个查询都需要 ID 和以下任一:post_namepost_titlepost_excerpt

如果它有助于简化事情。我正在尝试在这些列中搜索广泛匹配和完全匹配。

因此,在我的示例中,我将在以下列中查找:“地板饰面”、“地板”或“饰面”:post_namepost_titlepost_excerpt。都在同一个表中。

我已尝试使用 UNION 来完成此操作。

这是我的疑问:

Array
(
    [broad] => Array
        (
            [floor] => Array
                (
                    [slugs] => SELECT `ID`, `post_name` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_name` LIKE '%floor%'
                    [titles] => SELECT `ID`, `post_title` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_title` LIKE '%floor%'
                    [excerpts] => SELECT `ID`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_excerpt` LIKE '%floor%'
                )

            [finish] => Array
                (
                    [slugs] => SELECT `ID`, `post_name` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_name` LIKE '%finish%'
                    [titles] => SELECT `ID`, `post_title` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_title` LIKE '%finish%'
                    [excerpts] => SELECT `ID`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_excerpt` LIKE '%finish%'
                )

        )

    [exact] => Array
        (
            [slugs] => SELECT `ID`, `post_name` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_name` LIKE '%floor-finish%'
            [titles] => SELECT `ID`, `post_title` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_title` LIKE '%floor finish%'
            [excerpts] => SELECT `ID`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_excerpt` LIKE '%floor finish%'
        )

    [combined] => ( SELECT `ID`, `post_name` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_name` LIKE '%floor-finish%' ) UNION ( SELECT `ID`, `post_name` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_name` LIKE '%floor%' ) UNION ( SELECT `ID`, `post_name` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_name` LIKE '%finish%' ) UNION ( SELECT `ID`, `post_title` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_title` LIKE '%floor finish%' ) UNION ( SELECT `ID`, `post_title` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_title` LIKE '%floor%' ) UNION ( SELECT `ID`, `post_title` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_title` LIKE '%finish%' ) UNION ( SELECT `ID`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_excerpt` LIKE '%floor finish%' ) UNION ( SELECT `ID`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_excerpt` LIKE '%floor%' ) UNION ( SELECT `ID`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND `post_excerpt` LIKE '%finish%' )
)

但是,上面的结果很有趣。我似乎得到了所有正确的结果,除了每个结果值的键(应该是列的名称)始终保持不变。它始终是 post_name,即使分配给它的值可能是 post_titlepost_excerpt

所以每个结果都有一个IDpost_name。基本上它们的键是错误的,但值似乎是准确的。

我也尝试过这样的事情:

Array
        (
            [broad] => Array
                (
                    [floor] => SELECT `ID`, `post_name`, `post_title`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND ( `post_name` LIKE '%floor%' OR `post_title` LIKE '%floor%' OR `post_excerpt` LIKE '%floor' )
                    [finish] => SELECT `ID`, `post_name`, `post_title`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND ( `post_name` LIKE '%finish%' OR `post_title` LIKE '%finish%' OR `post_excerpt` LIKE '%finish%' )
                )

            [exact] => SELECT `ID`, `post_name`, `post_title`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND ( `post_name` LIKE '%floor-finish%' OR `post_title` LIKE '%floor finish%' OR `post_excerpt` LIKE '%floor finish%' )
            [combined] => SELECT `ID`, `post_name`, `post_title`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND ( `post_name` LIKE '%floor-finish%' OR `post_title` LIKE '%floor finish%' OR `post_excerpt` LIKE '%floor finish%' ) UNION (SELECT `ID`, `post_name`, `post_title`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND ( `post_name` LIKE '%floor%' OR `post_title` LIKE '%floor%' OR `post_excerpt` LIKE '%floor%' )) UNION (SELECT `ID`, `post_name`, `post_title`, `post_excerpt` FROM tps_3_posts WHERE `post_status` = 'publish' AND ( `post_name` LIKE '%finish%' OR `post_title` LIKE '%finish%' OR `post_excerpt` LIKE '%finish%' ))
        )

)

这更符合我想要完成的目标。我希望每个结果都有IDpost_excerptpost_slugpost_title。如果不匹配,则将它们的键显示为空值,或者完全不显示键。

第二次尝试的问题在于,它只需要在所需的三个列之一中进行匹配。因此,如果它在post_excerpt 中匹配并且没有在其他位置匹配,它仍然会从post_titlepost_name 中提取值。从而导致结果不准确。

我已经阅读了几个看似相似的问题,但大多数都没有真正可靠的明确答案......或者......问题/答案更适合 SEPARATE 表上的多个查询。

对在同一张表上组合多个 MySQL 查询有任何指导或建议吗?

顺便说一句...我在两个示例中都使用“组合”作为发送到数据库的最终查询。

所以再一次...如果列中没有匹配项,则将它们的键显示为 null 或完全从结果中完全省略键。

【问题讨论】:

    标签: php mysql sql database wordpress


    【解决方案1】:

    由于查询中的 UNION 语句,您得到了错误的“密钥”。您有不同的键名,但在联合查询的三个不同列之间具有兼容的列类型。数据库引擎不会抛出错误,而是从第一个查询中选择列名并将其用于所有查询:

    id | post_name # <= column name in first query
    1  | "my post"
    
    UNION
    
    id | post_title # <= column name is different, but type is compatible, so UNION succeeds
    1  | "my post title"
    
    UNION
    
    id | post_excerpt # <= ditto
    1  | "my post excerpt"
    

    会导致:

    id | post_name # <= column name from first query
    1  | "my post"
    1  | "my post title"
    1  | "my post excerpt"
    

    这是你正在经历的。

    相反,您可以执行以下操作:

    id | post_name | post_title | post_excerpt
    1  | "my post" | null       | null        # <= deliberately select nulls for these columns in this query
    
    UNION
    
    id | post_name | post_title      | post_excerpt
    1  | null      | "my post title" | null
    
    UNION
    
    id | post_name | post_title | post_excerpt
    1  | null      | null       | "my post excerpt"
    

    这会给你这样的结果:

    id | post_name | post_title      | post_excerpt
    1  | "my post" | null            | null
    1  | null      | "my post title" | null
    1  | null      | null            | "my post excerpt"
    

    对于您的表格,一个非常基本的版本可能如下所示:

    SELECT ID, post_name, null AS post_title, null AS post_excerpt FROM tps_3_posts
    
    UNION
    
    SELECT ID, null AS post_name, post_title, null AS post_excerpt FROM tps_3_posts
    
    UNION
    
    SELECT ID, null AS post_name, null AS post_title, post_excerpt FROM tps_3_posts
    

    这可能更适合您尝试做的事情。 Here's a SQLFiddle 如果你想看到它的实际效果。

    【讨论】:

    • 我想我明白你的建议。我应该在每个查询中选择所有 4 列,但强制某些列为空?这似乎是一个愚蠢的问题,但是您如何故意为某些列选择空值而不为其他列选择空值?
    • @MichaelEcklund 查看我更新的基本查询示例的答案。
    • 非常感谢保罗。这正是我需要做的。顺便说一句,W3Schools 教我做SELECT column_name AS alias_name,你演示SELECT alias_name AS column_name。您的语法是 CORRECT,而 W3Schools 的语法是 INCORRECT。当我以 W3Schools 的方式执行此操作时,MySQL 会因语法无效而引发错误。以你的方式,它完美地运作。
    【解决方案2】:

    正如我在第二种情况下所理解的那样,问题是只有匹配的列应该有值,而其他列应该为空。对于这种情况,您可以在 SELECT 中使用 IF/ELSE 或 WHEN 语句。这个想法是您选择实际值是该列的值对应于预期值,否则为空。

    另一个潜在的解决方案是你可以写例如

    SELECT `ID`, `post_name`, `post_title`, 'post_excerpt'
    

    因此,您在 WHERE 语句中选择了作为条件的字符串值,以后可以使用该值来了解该行属于什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 2012-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多