通过存储在"外部"中的值来改进SQL查询以过滤结果表

时间:2018-03-27 12:09:39

标签: mysql sql database

为了简化操作,我们假设我有一张表格,代表非常简单的用户提要。

有两个"键"我的feed表中的列:

object_id它是不同资产的ID,例如评论,发帖等。

entity_type_id它基本上是对我数据库中另一个表的引用。

"孩子"表可以具有一些共同的属性,例如is_hiddenis_deletedis_locked(但不会在所有表格中复制它们)。

现在,我想根据这三个属性的值,实现一个过滤掉我的Feed项的过滤器。

到目前为止我做了什么?

SELECT `f`.* 
FROM `feed` `f`
WHERE 1
-- !!! Other filters goes here. ---
AND 
(
    --
    -- !!! Filter by status
    --
    (   -- "Locked" (not all children tables have this column)
        (
            `f`.`entity_type_id` = 1 AND `f`.`object_id` IN ( SELECT `fb_comment_id` FROM `comments` WHERE `is_locked` = 1  AND `fb_page_id` IN('0123456789') )
        )
        OR
        (
            `f`.`entity_type_id` = 4 AND `f`.`object_id` IN ( SELECT `fb_post_id` FROM `posts` WHERE `is_locked` = 1 AND `fb_page_id` IN('0123456789') )
        )
    ) 
    (   -- "Hidden" (not all children tables have this column)
        (
            `f`.`entity_type_id` = 1 AND `f`.`object_id` IN ( SELECT `fb_comment_id` FROM `comments` WHERE `is_hidden` = 1  AND `fb_page_id` IN('0123456789') )
        )
        OR
        (
            `f`.`entity_type_id` = 4 AND `f`.`object_id` IN ( SELECT `fb_post_id` FROM `posts` WHERE `is_hidden` = 1 AND `fb_page_id` IN('0123456789') )
        )
    ) 
    OR 
    (
        -- "Deleted"
        (
            `f`.`entity_type_id` = 1 AND `f`.`object_id` IN ( SELECT `fb_comment_id` FROM `comments` WHERE `is_deleted` = 1 AND `fb_page_id` IN ('0123456789') )
        ) 
        OR
        (
            `f`.`entity_type_id` = 3 AND `f`.`object_id` IN ( SELECT `insta_comment_id` FROM `instagram_comments` WHERE `is_deleted` = 1 AND `insta_profile_id` IN ('9876543210') )
        )
        OR 
        (
            `f`.`entity_type_id` = 4 AND `f`.`object_id` IN ( SELECT `fb_post_id` FROM `posts` WHERE `is_deleted` = 1 AND `fb_page_id` IN ('0123456789') )
        )
        OR 
        (
            `f`.`entity_type_id` = 5 AND `f`.`object_id` IN ( SELECT `insta_post_id` FROM `instagram_posts` WHERE `is_deleted` = 1 AND `insta_profile_id` IN ('9876543210') )
        )
    )
)

正如您所看到的,我正在使用子查询,但我想知道是否有更好的方法来编写此类查询?

2 个答案:

答案 0 :(得分:1)

一些提示:

  1. 尝试使用INNER JOIN而不是WHERE +相关查询。例如,创建一个包含子查询中所有表的表,并应用您的过滤器。不要忘记使用PROCEDURE ANALYSE和索引。
  2. 避免SELECT *,输入您需要的所有变量。
  3. 应用EXPLAIN以了解您可以改进脚本的位置。

答案 1 :(得分:1)

我不知道它是否更好,但是我创建了一个子查询,它将来自子表的必要标志字段进行联合,然后只进行常规连接以获取标志字段。如果其中一个表没有标志字段,则它可能只是假。

类似的东西:

SELECT `f`.* 
FROM `feed` `f`
JOIN
    (
        SELECT  
            1 AS `entity_type_id`
        ,   fb_comment_id AS `object_id`
        ,   is_locked
        ,   is_hidden
        ,   is_deleted
        FROM
            comments

        UNION ALL

        SELECT  
            4 AS `entity_type_id`
        ,   fb_post_id AS `object_id`
        ,   is_locked
        ,   is_hidden
        ,   is_deleted
        FROM
            posts

        UNION ALL

        SELECT  
            3 AS `entity_type_id`
        ,   insta_comment_id AS `object_id`
        ,   0 AS is_locked
        ,   0 AS is_hidden
        ,   is_deleted
        FROM
            instagram_comments

        UNION ALL

        SELECT  
            5 AS `entity_type_id`
        ,   insta_post_id AS `object_id`
        ,   0 AS is_locked
        ,   0 AS is_hidden
        ,   is_deleted
        FROM
            instagram_posts
    ) AS flag_summary ON (
        flag_summary.entity_type_id = f.entity_type_id
    AND flag_summary.object_id = f.object_id
    )