Как уменьшить объединения в подзапросе?

#mysql #sql

#mysql #sql

Вопрос:

Вот мой текущий запрос:

 SELECT q.type,
      q.author_id author,
      q.deleted,
      q.deleter_id,
      COUNT(DISTINCT a.id) answers_num,
      COUNT(DISTINCT v.id) votes_num,
FROM qanda q
LEFT  JOIN qanda a ON q.id = a.related
LEFT  JOIN votes v on q.id = v.post_id
WHERE q.id = ?
  

Это работает хорошо. Просто мне нужно добавить еще одну вещь (которая возвращает логическое значение by EXISTS ) в SELECT инструкции. Это:

 EXISTS (SELECT a.id, sum(vot.value) total_votes
        FROM qanda q
        LEFT JOIN qanda a on q.id = a.related
        LEFT JOIN votes vot ON a.id = vot.post_id
        WHERE q.type = 0         -- this is a question
          AND a.related = 1315   -- getting answers
        GROUP BY a.id
        HAVING total_votes
        ORDER BY total_votes DESC
        LIMIT1
) as HasAUpvotedAnswer
  

Хорошо, это тоже хорошо работает. Но я беспокоюсь о производительности. Как вы можете видеть, JOIN s этих двух запросов выше (которые будут объединены окончательно) похожи. Как сделать их более оптимальными?

Другими словами, как я могу объединить эти два вышеуказанных запроса в наиболее оптимальном случае?

Комментарии:

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

2. @MarcinJ Концептуально я пытаюсь сделать «вы не можете удалить свой вопрос, потому что в нем есть один ответ, за который проголосовали, или два ответа, или и т. Д.» Для веб-сайта вопросов и ответов, подобного ЭТОМУ.

3. имеют ли несколько строк, которые вы получаете через ЛЕВОЕ СОЕДИНЕНИЕ, одинаковые данные? если это так, вы могли бы в принципе РАЗДЕЛИТЬ свой результирующий набор. если нет, я бы посмотрел на условия объединения, если вы можете добавить дополнительные условия, чтобы сделать их отличными

4. @stack В настоящее время я не знаю, с какой проблемой вы столкнулись, поэтому важно поделиться парой строк, которые представляют то, что вы пытаетесь сделать. В вашем подзапросе EXISTS вы жестко запрограммировали некоторые идентификаторы, поэтому мы не можем выяснить, каковы условия объединения для связанного подзапроса. Вставьте пару строк из qanda и votes , а затем строки, которые вы ожидаете получить в результате вашего запроса. Люди не любят гадать, что вы пытаетесь сделать, как расположены ваши данные и т. Д.

Ответ №1:

Судя по вашему коду, y может использовать один запрос, используя условное выражение для суммы

 SELECT q.type,
      q.author_id author,
      q.deleted,
      q.deleter_id,
      COUNT(DISTINCT a.id) answers_num,
      COUNT(DISTINCT v.id) votes_num,
      IF (SUM(
        CASE WHEN q.type  = 0 AND a.related = 1315
          THEN v.value  else  0 END) > 0,1,0) 
      HasAUpvotedAnswer
FROM qanda q
LEFT  JOIN qanda a ON q.id = a.related
LEFT  JOIN votes v on q.id = v.post_id
WHERE q.id = ?
  

Комментарии:

1. 1) Круглые скобки в конце HasAUpvotedAnswer являются избыточными. 2) Он выдает: Unknown column 'v.votes' in 'field list'

2. ответ обновлен .. v.значение, а не v.голоса .. голоса — это таблица с псевдонимом v

3.В настоящее время значение HasAUpvotedAnswer равно 6 (для моего реального набора данных). Ожидалось, что я буду логическим значением (либо 0 или 1 , например, что EXISTS возвращает)

4. добавлено значение if sum> 0 для 1 или 0

5. Ну, видимо, это работает ..! Но я предполагаю, что логика неверна. Поскольку мы даже не учитываем значение голосов в ответах. Поскольку мы не объединяем таблицу ответов ( qanda as a ) с votes таблицей.