За последние 24 часа нас посетили 32522 программиста и 1755 роботов. Сейчас ищут 887 программистов ...

Оптимизация запроса на выборку из таблицы с 2 столбцами

Тема в разделе "MySQL", создана пользователем PCSpeaker, 28 май 2011.

  1. PCSpeaker

    PCSpeaker Активный пользователь

    С нами с:
    26 дек 2007
    Сообщения:
    84
    Симпатии:
    0
    Приветствую. Есть таблица с 2 столбцами id1 и id2.

    Код (Text):
    1. id1 id2
    2. 1   1
    3. 1   1
    4. 2   1
    5. 2   2
    6. 3   2
    7. 3   2
    8. 4   1
    9. 4   1
    10. 5   1
    11. 5   2
    Задача выбрать из нее такие значения первого столбца, чтобы значения во втором содержали одновременно несколько заданных значений.
    Например, мы выбираем такие значения первого, чтобы второй столбец содержал одновременно 1 и 2.
    Результатом будут 2 и 5, так как остальные содержат либо только 1, либо только 2, а нам нужно чтобы одновременно.

    На ум приходит следующий вариант.
    [sql]SELECT `id1` FROM table WHERE `id1` IN (SELECT `id1` FROM table WHERE `id2` = 1) and `id1` IN (SELECT `id1` FROM table WHERE `id2` = 2)[/sql]
    Но если значений будет 10 или 20, то получится 20 вложенных селектов. Можно ли как-то упростить? В идеале, конечно, получить одним запросом, но впринципе я не против того, чтобы разбить на несколько или обработать результат в цикле на php.
     
  2. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Сщас совру...

    SELECT `id1` FROM table WHERE `id2` = 1 and `id2` = 2
    group by id1
     
  3. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    никогда не выполнится
     
  4. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Конечно не выполнится - я же говорил, что совру ;)

    Если разновидностей значений во втором столбце немного, то можно так:
    SELECT `id1`, GROUP_CONCAT(DISTINCT id2 order by id2 asc) list FROM table
    WHERE id2 in(1, 2)
    group by id1
    having list = '1,2'

    или так, если список не нужен:
    SELECT `id1` FROM table
    WHERE id2 in(1, 2)
    group by id1
    having GROUP_CONCAT(DISTINCT id2 order by id2 asc) = '1,2'
     
  5. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Вариант с count():
    SELECT `id1` FROM table
    WHERE id2 in(1, 2)
    group by id1
    having count(DISTINCT id2) = 2
     
  6. PCSpeaker

    PCSpeaker Активный пользователь

    С нами с:
    26 дек 2007
    Сообщения:
    84
    Симпатии:
    0
    Спасибо за варианты.

    Данных в таблице довольно много и разновидностей около 100 разных цифр. Одновременно обычно запрашивается от 2 до 10. Потестировал, даже если выбирать с 2 значениями, то запрос занимал около 10 секунд. А такие показатели на живом сайте, безусловно, неприемлимы.

    А вот вариант с count() не попробовал, так как не совсем понял как его применять, если нужно выбрать не по двум id2, а, к примеру по трем.
     
  7. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Сделайте индексы правильные и будет Вам счастье.

    SELECT `id1` FROM table
    WHERE id2 in(1,2,3)
    group by id1
    having count(DISTINCT id2) = 3
     
  8. PCSpeaker

    PCSpeaker Активный пользователь

    С нами с:
    26 дек 2007
    Сообщения:
    84
    Симпатии:
    0
    Там же всего 2 столбца и оба индексные, так как связаны foreign key с другими таблицами. Или можно как-то хитрее сделать?

    Я правильно понимаю, что оно будет работать только в том случае, если во втором столбце содержатся только те значения по которым происходит выборка и никакие другие? К примеру если в id2 содержатся значения 1 2 3 4 5, а я выбираю по комбинации 2 3 5, то в выборку попадут не только 2 3 5, а любая уникальная тройка.
     
  9. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Сколько в таблице записей?

    Попытайте. 5 минут и Вы будете знать точный ответ. ;)
     
  10. PCSpeaker

    PCSpeaker Активный пользователь

    С нами с:
    26 дек 2007
    Сообщения:
    84
    Симпатии:
    0
    10 000 :oops:

    Спасибо, попробую отпишусь =) я вроде бы понял в чем тут фишка и оно и вправду будет работать как надо
     
  11. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Десять тысяч это ничто для БД - должно выполняться за тысячные, максимум сотые доли секунды даже без ключей. Ищите проблему в другом месте.