Почему запрос ниже не дает правильного вывода

#mysql #sql

#mysql #sql

Вопрос:

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

 DROP TEMPORARY TABLE IF EXISTS temp_table ;
 CREATE TEMPORARY TABLE IF NOT EXISTS temp_table AS (   
 SELECT A.ID, B.topic_name 
    FROM question_sets A 
    INNER JOIN topics B 
    ON A.topic_id = B.Id 
    WHERE  test_section_id = 3 
    AND exam_category_id = 2 
    ORDER BY appeared 
 );

SELECT ID,topic_name , 
       @rank := IF(@topic = topic_name, @rank   1, 1) AS ranking,
       @topic := topic_name 
FROM temp_table
ORDER BY topic_name DESC
  

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

1. Вы создаете таблицу с именем TEMPORARY и извлекаете из нее данные temp_table .

Ответ №1:

В более поздних версиях MySQL вам необходимо отсортировать данные в подзапросе перед использованием переменных. И вы не должны назначать переменную в одном выражении и использовать ее в другом.

Итак:

 SELECT ID,topic_name , 
       (@rank := IF(@topic = topic_name, @rank   1,
                    IF(@topic := topic_name, 1, 1)
                   )
       ) as ranking
FROM (SELECT tt.*
      FROM temp_table tt
      ORDER BY topic_name DESC
     ) tt CROSS JOIN
     (SELECT @topic := '', @rank := 0) params;
  

Вероятно, вам нужен второй ключ после topic_name DESC , если вы действительно хотите ранжировать по какому-либо столбцу. Вы не можете зависеть от порядка во временной таблице — потому что таблицы представляют неупорядоченные наборы.

В MySQL 8 вы бы просто сделали:

 select tt.*,
       row_number() over (partition by topic_name order by ?) as seqnum
from temp_table tt;
  

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

1. спасибо, я использовал одну переменную в другом выражении, поэтому я получаю тот же номер строки. В приведенном выше коде я добавил еще один вложенный запрос для сортировки строки по topic_name, поскольку он неправильно генерирует номер строки.

2. УДАЛИТЕ ВРЕМЕННУЮ ТАБЛИЦУ, ЕСЛИ СУЩЕСТВУЕТ temp_table; СОЗДАЙТЕ ВРЕМЕННУЮ ТАБЛИЦУ, ЕСЛИ НЕ СУЩЕСТВУЕТ temp_table КАК ( ВЫБЕРИТЕ ID, topic_name ИЗ ( ВЫБЕРИТЕ A.ID , B.topic_name ИЗ question_sets A ВНУТРЕННЕЕ ОБЪЕДИНЕНИЕ тем B В A.topic_id = B.Id ГДЕ появились test_section_id = 3 И exam_category_id = 2 ПОРЯДОК ПО ) ПОРЯДОК ПО topic_name );