合并依赖于另一个的结果集的查询

时间:2015-11-28 18:19:06

标签: mysql sql

我运行此查询以根据评级,类别等内容从我的wordpress数据库中获取20个随机项目

 SELECT (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category
            FROM `wp_gdsr_data_article` as A 
                INNER JOIN `wp_posts` as B ON (A.post_id = B.id) 
                INNER JOIN wp_term_relationships C ON (B.ID = C.object_id) 
                INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id) 
                INNER JOIN wp_terms E ON (D.term_id = E.term_id) 
            WHERE 
                B.post_type = 'post' AND
                B.post_status = 'publish' AND
                D.taxonomy='category' AND
                E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP') 
            ORDER BY RAND()
            LIMIT 20

然后,对于随机项的每个结果,我想找到一个与随机项非常相似的项目(大约相同的评级)但不相同,也是用户没有看到的项目:

SELECT ABS($site_rating-(A.user_votes/A.user_voters)) as diff, (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category ,IFNULL(F.count,0) as count
            FROM `wp_gdsr_data_article` as A 
                INNER JOIN `wp_posts` as B ON (A.post_id = B.id) 
                INNER JOIN wp_term_relationships C ON (B.ID = C.object_id) 
                INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id) 
                INNER JOIN wp_terms E ON (D.term_id = E.term_id) 
                LEFT JOIN (
                    SELECT *,COUNT(*) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
                ) as F ON (A.post_id = F.post_id_winner OR A.post_id = F.post_id_loser)
            WHERE 
                E.name = '$category' AND
                B.ID <> '$post_id' AND
                B.post_type = 'post' AND
                B.post_status = 'publish' AND
                D.taxonomy='category' AND
                E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP') 
            ORDER BY count ASC, diff ASC
            LIMIT 1

以下php变量引用上一个查询的结果

    $post_id = $result['post_id'];
    $category = $result['category'];
    $site_rating = $result['site_rating'];

$_SERVER['REMOTE_ADDR']是指用户的IP。

有没有办法将第一个查询与需要调用的20个其他查询结合起来查找相应的项目,这样我只需要1或2个查询?

编辑:这是简化连接的视图

CREATE VIEW `versus_random` AS
SELECT (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category 
FROM `wp_gdsr_data_article` as A 
    INNER JOIN `wp_posts` as B ON (A.post_id = B.id) 
    INNER JOIN wp_term_relationships C ON (B.ID = C.object_id) 
    INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id) 
    INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE 
    B.post_type = 'post' AND
    B.post_status = 'publish' AND
    D.taxonomy='category' AND
    E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP') 

我现在尝试了以下观点:

 SELECT post_id, 
    (
            SELECT INNER_TABLE.post_id
            FROM `versus_random` as INNER_TABLE
            WHERE 
                INNER_TABLE.post_id <> OUTER_TABLE.post_id
            ORDER BY (SELECT COUNT(*) FROM `versus` WHERE ip = '54' AND (INNER_TABLE.post_id = post_id_winner OR INNER_TABLE.post_id = post_id_loser)) ASC
            LIMIT 1
        ) as innerquery

    FROM `versus_random` as OUTER_TABLE
    ORDER BY RAND()
    LIMIT 20

然而查询只是超时并冻结了我的mysql。

2 个答案:

答案 0 :(得分:1)

认为它应该像这样工作,但我手边没有任何Wordpress来测试它。获取相关帖子的第二个查询嵌入到另一个查询中,只有related_post_id。在给定别名“X”的情况下,整个查询将变为子查询本身(尽管如果您想继续使用字母表,可以自由使用“G”。)

在外部查询中,post和data-article的表再次连接(RA和RP),以根据内部查询中的related_post_id查询相关帖子的相关字段。这两个表保持连接(并且顺序相反),因此如果没有找到相关帖子,你仍然可以获得主帖。

SELECT 
  X.site_rating,
  X.post_id,
  X.post_author,
  X.post_date,
  X.category,
  RA.user_votes / RA.user_voters as related_post_site_rating, 
  RP.ID as related_post_id, 
  RP.post_author as related_post_author, 
  RP.post_date as related_post_date,
  RP.name as related_category,
FROM       
  ( SELECT 
      (A.user_votes/A.user_voters) as site_rating, 
      B.ID as post_id, B.post_author, B.post_date,E.name as category,
      ( SELECT 
          RB.ID as post_id
        FROM `wp_gdsr_data_article` as RA 
            INNER JOIN `wp_posts` as RB ON (RA.post_id = RB.id) 
            INNER JOIN wp_term_relationships RC ON (RB.ID = RC.object_id) 
            INNER JOIN wp_term_taxonomy RD ON (RC.term_taxonomy_id = RD.term_taxonomy_id) 
            INNER JOIN wp_terms RE ON (RD.term_id = RE.term_id) 
            LEFT JOIN (
                SELECT *,COUNT(*) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
            ) as RF ON (RA.post_id = RF.post_id_winner OR RA.post_id = RF.post_id_loser)
        WHERE 
            RE.name = E.name AND
            RB.ID <> B.ID AND
            RB.post_type = 'post' AND
            RB.post_status = 'publish' AND
            RD.taxonomy='category' AND
            RE.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP') 
        ORDER BY count ASC, diff ASC
        LIMIT 1) as related_post_id

    FROM `wp_gdsr_data_article` as A 
        INNER JOIN `wp_posts` as B ON (A.post_id = B.id) 
        INNER JOIN wp_term_relationships C ON (B.ID = C.object_id) 
        INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id) 
        INNER JOIN wp_terms E ON (D.term_id = E.term_id)
    WHERE 
        B.post_type = 'post' AND
        B.post_status = 'publish' AND
        D.taxonomy='category' AND
        E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP') 
    ORDER BY RAND()
    LIMIT 20
  ) X
  LEFT JOIN `wp_posts` as RP ON RP.id = X.related_post_id 
  LEFT JOIN `wp_gdsr_data_article` as RA.post_id = RP.id

答案 1 :(得分:1)

我无法测试我的建议,所以请怀疑。无论如何,我希望它可以成为面临的一些问题的有效起点。

我无法想象一个解决方案没有通过临时表,在您的查询中布线繁重的计算。您还可以实现不干扰第一阶段随机化的目标。在下面我试着澄清一下。

我将从这些改写开始:

-- first query 
SELECT site_rating, post_id, post_author, post_date, category
    FROM POSTS_COMMON   
ORDER BY RAND()
LIMIT 20

-- second query 
SELECT ABS(R.site_rating_A - R.site_rating_B) as diff, R.site_rating_B as site_rating, P.post_id, P.post_author, P.post_date, P.category, F.count 
    FROM POSTS_COMMON AS P 
        INNER JOIN POSTS_RATING_DIFFS AS R ON (P.post_id = R.post_id_B)
        LEFT JOIN (     
            /* post_id_winner, post_id_loser explicited; COUNT(*) NULL treatment anticipated */
            SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
        ) as F ON (P.post_id = F.post_id_winner OR P.post_id = F.post_id_loser)
    WHERE 
        P.category = '$category'
        AND R.post_id_A = '$post_id'
    ORDER BY count ASC, diff ASC
    LIMIT 1         

使用:

SELECT A.post_id_A, B.post_id_B, A.site_rating as site_rating_A, B.site_rating as site_rating_B
INTO POSTS_RATING_DIFFS
    FROM POSTS_COMMON as A, POSTS_COMMON as B 
    WHERE A.post_id <> B.post_id AND A.category = B.category

CREATE VIEW POSTS_COMMON AS 
    SELECT  A.ID as post_id, A.user_votes, A.user_voters, (A.user_votes / A.user_voters) as site_rating, B.post_author, B.post_date, E.name as category
        FROM wp_gdsr_data_article` as A 
            INNER JOIN  `wp_posts` as B ON (A.post_id = B.post_id)
            INNER JOIN wp_term_relationships C ON (B.ID = C.object_id) 
            INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id) 
            INNER JOIN wp_terms E ON (D.term_id = E.term_id) 
        WHERE 
            B.post_type = 'post' AND
            B.post_status = 'publish' AND
            D.taxonomy='category' AND
            E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP') 

POSTS_COMMON隔离了两个查询之间的公共视图。

使用POSTS_RATING_DIFFS,一个填充了评级组合和差异的临时表,我们有“诀窍”在post_id(s)上以相等的方式转换不等式连接条件(参见{{ 1}}在第二个查询中。)

我们还利用临时表格对R.post_id_A = '$post_id'的组合爆炸进行预先计算评级(与职位类别相等),而且对其他会话有用。

同样提取临时表中的A.post_id <> B.post_id排序可能是有利的。在这种情况下,我们可以限制评级组合和差异仅在随机选择的20个。

依赖于第二级查询的原始限制是通过排序和限制语句来完成。 建议的解决方案避免在第二级查询中的RAND()结果集上详细阐述LIMIT 1,该查询成为子查询。

子查询中的单行计算是通过ORDER BY条件来完成的,该条件是根据使用WHERE子句的列值计算的单个值的最大值。

组合成单个值必须在保留正确排序时有效。我会留下伪代码:

  

ORDER BY

例如,将两个值组合成字符串类型,我们可以:

'<combination of count and diff>'

单个查询的结构将是:

CONCAT(LPAD(CAST(count AS CHAR), 10, '0'), LPAD(CAST(ABS(diff) AS CHAR), 20, '0'))

SELECT (Q_LVL_1.user_votes/Q_LVL_1.user_voters) as site_rating_LVL_1, Q_LVL_1.post_id as post_id_LVL_1 , Q_LVL_1.post_author as post_author_LVL_1, Q_LVL_1.post_date as post_date_LVL_1 , Q_LVL_1.category as category_LVL_1, Q_LVL_2.post_id as post_id_LVL_2 , Q_LVL_2.diff as diff_LVL_2, Q_LVL_2.site_rating as site_rating_LVL_2 , Q_LVL_2.post_author as post_author_LVL_2, Q_LVL_2.post_date as post_date_LVL_2 , Q_LVL_2.count FROM POSTS_COMMON AS Q_LVL_1 , /* 1-row-selection query placed side by side for each Q_LVL_1's row */ ( SELECT CORE_P.post_id, CORE_P.ABS_diff as diff, P.site_rating, P.post_author, P.post_date, CORE_P.count FROM POSTS_COMMON AS P INNER JOIN ( SELECT FIRST(CORE_P.post_id) as post_id, ABS(CORE_P.diff) as ABS_diff, CORE_P.count FROM ( /* selection of posts with post_id(s) different from first level query, not already taken and with the topmost value of '<combination of count and diff>' */ ) AS CORE_P GROUP BY CORE_P.count, ABS(CORE_P.diff) /* the one row selector */ ) AS CORE_ONE_LINER ON P.post_id = CORE_ONE_LINER.post_id ) AS Q_LVL_2 ORDER BY RAND() LIMIT 20 选择可能会有更多CORE_P (s)与最高值post_id对应,因此使用'<combination of count and diff>'和{{ 1}}条款到达单行。

这带来了可能的最终实施:

GROUP BY