Объединение нескольких запросов по одной строке и порядок по всем - PullRequest
0 голосов
/ 21 марта 2012

У меня есть три разных запроса, которые имеют одну общую строку (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 ]

2 голосов
/ 21 марта 2012
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 (SELECT user_id, COUNT () AS комментарии, комментарии FROM (SELECT COUNT () AS) комментарии FROM prognose_ccomments cc ВЛЕВО СОЕДИНЕНИЕ prognose_comments p ON cc.post_id = p.p_id) AStmp_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
) 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 голос
/ 22 марта 2012

Рад знать, что это работает для вас.

Для вашего последнего требования я бы использовал 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
1 голос
/ 21 марта 2012
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.

...