通过单行合并多个查询并按顺序合并

时间:2012-03-21 15:28:06

标签: sql join merge union

我有三个不同的查询,它们有一个共同的行(user_id),应该在一个查询中组合以应用排序。如果一个或多个查询结果为空集,它也应该有效。

查询1:

SELECT
    user_id,
    COUNT(answer) AS total_predictions    
FROM
    prognose_predictions pc
INNER JOIN prognose_prognose pp
    ON pp.prognose_id = '9'
    AND pc.prognose_id = '9'
    AND pc.prognose_id = pp.prognose_id
GROUP BY 
    user_id
ORDER BY 
    user_id ASC

查询2:

SELECT
    user_id,
    COUNT(*) AS comments,
    ccomments
FROM 
(
    SELECT
        COUNT(*) AS ccomments
    FROM
        prognose_ccomments cc
    LEFT JOIN prognose_comments p
        ON cc.post_id = p.p_id
)   AS tmp_table,
    prognose_comments c
INNER JOIN prognose_prognose x
    ON x.prognose_id = c.prognose_id AND c.prognose_id = 9
GROUP BY
    c.user_id
ORDER BY 
    c.user_id ASC

查询3:

SELECT
    user_id,
    COUNT(*) as logins
FROM
    prognose_activitylog a
WHERE 
    login_time BETWEEN '33333333333' AND '4444444444'
GROUP BY 
    user_id

我想有这个:

user_id | total_predictions | comments | ccomments | logins
1       | 3                 | 0        | 0         | 7
6       | 6                 | 1        | 3         | 4
7       | 0                 | 0        | 0         | 1

其中“0”表示表中没有数据,但user_id仍然可用。 通过这种逻辑,我可以在PHP中更好地处理这些数据。

如何实现这一目标?

===================================

@Tad:错误的最新查询“字段列表中的列'user_id'不明确”

SELECT
            user_id,
            total_predictions,
            IFNULL(comments, '0')  AS comments ,
            IFNULL(ccomments, '0') AS ccomments,
            IFNULL(logins,'0')     AS logins
        FROM
            (
                SELECT
                    user_id,
                    total_predictions,
                    (
                        -- Get comments from Query 2
                        SELECT
                            comments
                        FROM
                            (
                                SELECT
                                    COUNT(*) AS comments,
                                    user_id
                                FROM
                                    (
                                        SELECT
                                            COUNT(*) AS ccomments
                                        FROM
                                            prognose_ccomments cc
                                        LEFT JOIN
                                            prognose_comments p
                                        ON
                                            cc.post_id = p.p_id ) AS tmp_table,
                                    prognose_comments c
                                INNER JOIN
                                    prognose_prognose x
                                ON
                                    x.prognose_id = c.prognose_id
                                AND c.prognose_id = '9'
                                GROUP BY
                                    c.user_id ) AS Query2
                        WHERE
                            Query1.user_id = Query2.user_id ) AS comments,
                    (
                        -- Get ccomments from Query2
                        SELECT
                            ccomments
                        FROM
                            (
                                SELECT
                                    ccomments,
                                    user_id
                                FROM
                                    (
                                        SELECT
                                            COUNT(*) AS ccomments
                                        FROM
                                            prognose_ccomments cc
                                        LEFT JOIN
                                            prognose_comments p
                                        ON
                                            cc.post_id = p.p_id ) AS tmp_table,
                                    prognose_comments c
                                INNER JOIN
                                    prognose_prognose x
                                ON
                                    x.prognose_id = c.prognose_id
                                AND c.prognose_id = '9'
                                GROUP BY
                                    c.user_id )AS Query2
                        WHERE
                            Query1.user_id = Query2.user_id ) AS ccomments,
                    (
                        -- Get logins from Query3
                        SELECT
                            logins
                        FROM
                            (
                                SELECT
                                    user_id,
                                    COUNT(*) AS logins
                                FROM
                                    prognose_activitylog a
                                WHERE
                                    login_time BETWEEN '1332284401' AND '1333058399'
                                GROUP BY
                                    user_id )AS Query3
                        WHERE
                            Query1.user_id = Query3.user_id ) AS logins
                FROM
                    (
                        -- Get product_Num logins and total_predictions from Query 1
                        SELECT
                            user_id,
                            COUNT(answer) AS total_predictions
                        FROM
                            prognose_predictions pc
                        INNER JOIN
                            prognose_prognose pp
                        ON
                            pp.prognose_id = '9'
                        AND pc.prognose_id = '9'
                        AND pc.prognose_id = pp.prognose_id
                        GROUP BY
                            user_id )AS Query1 )AS FinalQuery
                                                    INNER JOIN prognose_users ON prognose_users.User_ID = FinalQuery.user_id
        ORDER BY
            total_predictions DESC,
            comments DESC,
            ccomments DESC,
            logins DESC LIMIT 0,10 ;

3 个答案:

答案 0 :(得分:2)

SELECT A.user_id,COALESCE(A.total_predictions,0),B.comments,COALESCE(B.ccomments,0),COALESCE(C.logins,0) FROM 
(
SELECT
        user_id,
        COUNT(answer) as total_predictions

    FROM
        prognose_predictions pc
    INNER JOIN
        prognose_prognose pp
    ON
        pp.prognose_id = '9'
    AND pc.prognose_id = '9'
    AND pc.prognose_id = pp.prognose_id

   GROUP BY user_id
   ORDER BY user_id ASC
) A 

INNER JOIN     (     选择             用户身份,             COUNT()AS评论,             ccomments         从             (                 选择                     COUNT()AS ccomments                 从                     prognose_ccomments cc                 LEFT JOIN                     prognose_comments p                 上                     cc.post_id = p.p_id)AS tmp_table,             prognose_comments c         内部联接             prognose_prognose x         上             x.prognose_id = c.prognose_id AND c.prognose_id = 9         通过...分组             c.user_id

    ORDER BY c.user_id ASC
) B
ON  A.user_id = B.user_id 
RIGHT OUTER JOIN 
(
SELECT
        user_id,
        COUNT(*) as logins
    FROM
        prognose_activitylog a
     WHERE login_time BETWEEN '33333333333' AND '4444444444'
        GROUP BY user_id
) C
ON  B.user_id = C.user_id
ORDER BY A.user_id;

答案 1 :(得分:1)

Hope the following works fine except it's lengthy:

        SELECT [user_id], total_predictions, ISNULL(comments, ''), ISNULL(ccomments, ''), ISNULL(logins, '')
        FROM 
        (
            SELECT [user_id], total_predictions,
                    (
                        --Get comments from Query 2
                        SELECT comments 
                        FROM
                        (
                            SELECT COUNT(*) AS comments
                            FROM         
                            (
                                SELECT COUNT(*) AS ccomments             
                                FROM prognose_ccomments cc             
                                LEFT JOIN  prognose_comments p  ON  cc.post_id = p.p_id
                            ) AS tmp_table,  prognose_comments c     
                            INNER JOIN prognose_prognose x  ON  x.prognose_id = c.prognose_id AND c.prognose_id = 9
                            GROUP BY  c.user_id      
                            --ORDER BY c.user_id ASC 
                        ) AS Query2
                        WHERE Query1.[user_Id] = Query2.[user_id]
                    ) AS comments,
                    (
                        --Get ccomments from Query2
                        SELECT ccomments  
                        FROM 
                        (
                            SELECT ccomments     
                            FROM         
                            (
                                SELECT COUNT(*) AS ccomments             
                                FROM prognose_ccomments cc             
                                LEFT JOIN  prognose_comments p  ON  cc.post_id = p.p_id
                            ) AS tmp_table,  prognose_comments c     
                            INNER JOIN prognose_prognose x  ON  x.prognose_id = c.prognose_id AND c.prognose_id = 9
                            GROUP BY c.user_id      
                            --ORDER BY c.user_id ASC 
                        )AS Query2
                        WHERE Query1.[user_Id] = Query2.[user_id]
                    ) AS ccomments,
                    (
                        --Get logins from Query3
                        SELECT logins  
                        FROM 
                        (
                            SELECT   user_id, COUNT(*) as logins     
                            FROM  prognose_activitylog a      
                            WHERE login_time BETWEEN '33333333333' AND '4444444444'         
                            GROUP BY user_id 
                        )AS Query3
                        WHERE Query1.[user_Id] = Query3.[user_id]
                    ) AS logins

            FROM
            (     
                --Get [user_id] logins and total_predictions from Query 1
                SELECT [user_id], COUNT(answer) AS total_predictions
                FROM  prognose_predictions pc     
                INNER JOIN   prognose_prognose pp ON pp.prognose_id = '9' AND pc.prognose_id = '9' AND pc.prognose_id = pp.prognose_id     
                GROUP BY [user_id]  
                --ORDER BY [user_id] ASC   
            )AS Query1
        )AS FinalQuery
        ORDER BY [user_id]

抱歉,我在MS SQL Server 2005中测试了该查询。但是,应该可以将此相同的查询转换为其MySQL等价物。为此,可以从[从中导出上述查询]下面的简化测试查询开始:

                    SELECT user_id, total_predictions, ISNULL(comments, '') AS Comments, ISNULL(ccomments, '') AS ccomments, ISNULL(logins,'') AS logins
                    FROM 
                    (
                        SELECT user_id, total_predictions,
                            (
                                --Get comments from Query 2
                                SELECT comments 
                                FROM
                                (
                                    SELECT '1' AS user_id, 'comments' AS comments --Later on replace this with your Query 2 after removing the ORDER BY 
                                ) AS Query2
                                WHERE Query1.user_id =  Query2.user_id
                            ) AS comments,
                            (
                                --Get ccomments from Query2
                                SELECT ccomments  
                                FROM 
                                (
                                    SELECT '1' AS user_id, 'ccomments' AS ccomments --Later on replace this with your Query 2 after removing the ORDER BY 
                                )AS Query2
                                WHERE Query1.user_id =  Query2.user_id
                            ) AS ccomments,
                            (
                                --Get logins from Query3
                                SELECT logins  
                                FROM 
                                (
                                    SELECT '1' AS user_id, 'logins' AS logins  --Later on replace this with your Query 3 after removing the ORDER BY 
                                )AS Query3
                                WHERE Query1.user_id =  Query3.user_id
                            ) AS logins

                        FROM
                        (     
                            --Get product_Num logins and total_predictions from Query 1
                            SELECT '1' AS user_id, 'total_predictions' AS total_predictions -- Later on replace this with your Query 1 after removing the ORDER BY 
                        )AS Query1
                    )AS FinalQuery
                    ORDER BY user_id

从MySQL命令行代码执行的MySQL查询版本:

    mysql>       SELECT user_id, total_predictions, IFNULL(comments, '') AS Comments 
 , IFNULL(ccomments, '') AS ccomments, IFNULL(logins,'') AS logins 
  ->       FROM 
  ->       ( 
  ->        SELECT user_id, total_predictions, 
  ->         ( 
  ->          -- Get comments from Query 2 
  ->          SELECT comments 
  ->          FROM 
  ->          ( 
  ->           SELECT '1' AS user_id, 'comments' AS comments -- Later on replace this with your Query 2 after removing the ORDER BY 
  ->          ) AS Query2 
  ->          WHERE Query1.user_id =  Query2.user_id 
  ->         ) AS comments, 
  ->         ( 
  ->          -- Get ccomments from Query2 
  ->          SELECT ccomments 
  ->          FROM 
  ->          ( 
  ->           SELECT '1' AS user_id, 'ccomments' AS ccomments -- Later on replace this with your Query 2 after removing the ORDER BY 
  ->          )AS Query2 
  ->          WHERE Query1.user_id =  Query2.user_id 
  ->         ) AS ccomments, 
  ->         ( 
  ->          -- Get logins from Query3 
  ->          SELECT logins 
  ->          FROM 
  ->          ( 
  ->           SELECT '1' AS user_id, 'logins' AS logins  -- Later on replace this with your Query 3 after removing the ORDER BY 
  ->          )AS Query3 
  ->          WHERE Query1.user_id =  Query3.user_id 
  ->         ) AS logins 
  ->        FROM 
  ->        ( 
  ->         -- Get product_Num logins and total_predictions from Query 1 
  ->         SELECT '1' AS user_id, 'total_predictions' AS total_predictions --  Later on replace this with your Query 1 after removing the ORDER BY 
  ->        )AS Query1 
  ->       )AS FinalQuery 
  ->       ORDER BY user_id 
  -> 
  ->  ; 
  +---------+-------------------+----------+-----------+--------+ 
  | user_id | total_predictions | Comments | ccomments | logins | 
  +---------+-------------------+----------+-----------+--------+ 
  | 1       | total_predictions | comments | ccomments | logins | 
  +---------+-------------------+----------+-----------+--------+ 
  1 row in set (0.06 sec) 

仅供参考,为了将简化的测试查询转换为MySQL查询,我做了两个小的改动: 1)ISNULL到IFNULL(如前所述);和 2)MySQL注释中的第二个破折号后面应至少跟一个空格。示例: - 从查询2获取注释。在转换之前,“ - ”和“Get”之间没有空格,因为空格在MS SQL Server中是可选的。

答案 2 :(得分:1)

很高兴知道它适合你。

对于您的最新要求,我将使用INNER JOIN,如下所示:

           SELECT user_id, user_name, email, phone, total_predictions, IFNULL(comments, '0') AS Comments   , IFNULL(ccomments, '0') AS ccomments, IFNULL(logins,'0') AS logins  
           FROM 
           (
           -- All the sub queries go here
           )AS FinalQuery
           INNER JOIN prognose_users ON prognose_users.user_id = FinalQuery.user_id