Как использовать подзапрос внутри другого подзапроса с тремя таблицами в mysql?

У меня есть три таблицы в моей базе данных, см. структуру ниже:

пользователи

uid | fname | date_joined
---------------------------------
 1  | john  | 2013-08-25 01:00:00
 2  | rock  | 2013-08-26 01:00:00
 3  | jane  | 2013-08-27 01:00:00

вопросы

qid | uid 
---------- 
 1  |  1   
 2  |  1   
 3  |  2   
 4  |  3   
 5  |  3   
 6  |  1   
 7  |  1   
 8  |  2   
 9  |  2   

подписчики

fid | qid
---------
 1  |  2
 2  |  1
 3  |  2
 4  |  1
 5  |  2
 6  |  3
 7  |  2

пользовательская таблица содержит все поля, связанные с пользователем
таблица вопросов содержит все данные, связанные с вопросом, с внешним ключом uid
таблица подписчиков хранит информацию о том, сколько раз последовал вопрос

Я хочу, чтобы мой запрос возвращал следующее:

unique uid, 
fname
question count for each user
follower count for each user

Я написал запрос, и он работает нормально и возвращает записи, как я хочу, но количество подписчиков всегда равно 0. Вот мой запрос:

SELECT 
    u.uid, u.fname, u.date_joined , 
    (SELECT COUNT(*) FROM questions WHERE questions.uid = u.uid) AS question_count,
    (SELECT COUNT(*) FROM followers WHERE followers.qid IN ( 
        SELECT GROUP_CONCAT(qid) FROM questions WHERE questions.uid = u.uid 
        ) 
    ) AS follow_count
FROM epc_user AS u
ORDER BY follow_count DESC, question_count DESC, date_joined DESC

Я пробовал несколько разных комбинаций, но ни одна из них не сработала, возможно, я пишу неправильный запрос или невозможно использовать подзапрос в другом подзапросе, что бы это ни было. Я просто хочу знать, возможно ли это или нет, и если возможно


person Murtaza Malek    schedule 31.08.2013    source источник


Ответы (2)


GROUP_CONCAT вернет строку, но оператор IN работает с набором значений, а не со строкой, поэтому вам нужно использовать что-то вроде этого

   SELECT 
        u.uid, u.fname, u.date_joined , 
        (SELECT COUNT(*) FROM questions WHERE questions.uid = u.uid) AS question_count,
        (SELECT COUNT(*) FROM followers WHERE followers.qid IN ( 
            SELECT qid FROM questions WHERE questions.uid = u.uid 
            ) 
        ) AS follow_count
    FROM users AS u
    ORDER BY follow_count DESC, question_count DESC, date_joined DESC

скрипка: http://sqlfiddle.com/#!2/8cd10/2

person Ashish Gaur    schedule 31.08.2013
comment
Спасибо за выяснение проблемы, да, это сработало, но решение, предоставленное @slaakso, более надежно, когда я запускаю оба запроса в профилировщике. Существует разница от 0,0002 секунды (при использовании соединения) до 0,0048 секунды (при использовании подзапроса). - person Murtaza Malek; 31.08.2013
comment
@murtazamalek Нет проблем, но он пропустил столбцы order by clause и date_joined, вы можете проверить полный запрос здесь - person Ashish Gaur; 31.08.2013
comment
Да, ты прав. Stackoverflow разработан, чтобы предоставить правильное решение, и это то, что вы сделали. Спасибо. - person Murtaza Malek; 31.08.2013
comment
snyder, вы можете помочь мне узнать ранг для каждой строки? Я попробовал mysql @variables, чтобы получить ранг, но поскольку наш запрос группирует значения, ранжирование не работает должным образом. - person Murtaza Malek; 31.08.2013
comment
@murtazamalek для группы, заданной запросом slaakso, вы можете использовать это, а для моего ответа вы можно использовать это - person Ashish Gaur; 31.08.2013

Вы можете использовать соединения, чтобы получить результат. Нет необходимости в подзапросах:

select 
  u.uid, 
  u.fname, 
  u.date_joined, 
  count( distinct q.qid ) as 'question_count', 
  count( distinct f.fid ) as 'follower_count'
from users u
  left join questions q on q.uid = u.uid
  left join followers f on f.qid = q.qid
group by u.uid, u.fname, u.date_joined
order by follower_count desc, question_count desc, date_joined desc;
person slaakso    schedule 31.08.2013