2 разных запроса с небольшим запросом и 1 с подзапросом

У меня есть таблица вроде этого

name       | personal_number 
-----------------------------------------
Jon        | 222
Alex       | 555
Jon        | 222
Jimmy      | 999

Мне нужно получить каждое имя, которое персональное_состояние повторяется в таблице более 1, то есть результат должен быть:

 Jon        
 Jon        

Итак, вариант 1):

SELECT  name  FROM mytable WHERE personal_number IN (
        SELECT  personal_number  FROM mytable  GROUP BY personal_number
        HAVING COUNT(*) > 1
)

Вариант 2):

SELECT  personal_number  FROM mytable  GROUP BY personal_number
        HAVING COUNT(*) > 1
)

Затем, используя php, извлеченные персональные_нимеры соединяются как строка (soemthing like this '222', '222') и запускают другой запрос

SELECT  name FROM mytable  WHERE personal_number IN( here joined string )

Вариант 2 работает примерно в 10 раз быстрее, чем вариант 1, это для меня неожиданно, я думал, что один запрос будет быстрее, но...

(В таблице 500 000 строк, столбец personal_number не проиндексирован)

Итак, что вы имеете в виду о таких случаях? почему вариант 2 намного быстрее, чем вариант 1?

Ответ 2

Первый запрос имеет тяжелый подзапрос. Вы должны избегать этого. Лучшим решением для вашей проблемы является только один запрос:

SELECT name FROM mytable GROUP BY personal_number HAVING COUNT(*) > 1;

Этот запрос возвращает вам каждое повторное имя только один раз. Если вы хотите отображать имя дубликата столько раз, сколько они встречались, вы должны использовать следующий запрос:

SELECT name, COUNT(*) AS count FROM mytable GROUP BY personal_number HAVING COUNT(*) > 1;

И затем в PHP сделайте что-то вроде этого:

foreach ($rows as $row) {
  for ($i = 0; $i++; $i < $row['count']) {
    echo $row['name'] . "\n";
  }
}

Ответ 3

Это должно быть быстрее:

SELECT  name  FROM mytable join (
        SELECT  personal_number  FROM mytable  GROUP BY personal_number
        HAVING COUNT(*) > 1
)a using (personel_number)

Изменить: если это быстрее, чем вариант 1, то это означает, что в варианте 1 mysql снова и снова воспроизводит внутреннюю таблицу для каждой записи.

Ответ 4

Так как индексация не выполняется, так что 1 медленный, так как он должен соответствовать личным_знакам из выбранных персональных номеров. Если индексирование выполняется, оно потребляет меньше времени, чем раньше. Вариант 2 является прямым запросом, следовательно, он быстрее.