Подскажите как объединить 2 запроса в 1: Код (Text): SELECT DISTINCT theme.city_id, city.id, city.parent FROM theme, city WHERE theme.city_id = city.id SELECT * FROM city WHERE id IN(паренты предыдущего запроса) почитал учебник Мартина Грабера, попробовал коррелированный подзапрос: Код (Text): SELECT * FROM city WHERE city.id IN (SELECT DISTINCT theme.city_id, city.id, city.parent FROM theme, city WHERE theme.city_id = city.id) ничего не получилось, выдало ошибку: Operand should contain 1 column(s)
Если честно - совсем непонятно, что именно ты хочешь сделать данным запросом. Если можно - выложи структуру таблиц и опиши задачу
Код (Text): SELECT DISTINCT theme.city_id, city.id, city.parent FROM theme, city WHERE theme.city_id = city.id получаем данные по городам по которым есть темы и получаем паренты(вышестоящие регионы городов) Код (Text): city_id id parent 46 46 2 252 252 4 464 464 9 Код (Text): SELECT * FROM city WHERE id IN(паренты предыдущего запроса) получаем полные данные о регионе т.е. нужно вывести регионы, города которых есть в темах в таблице theme есть id, title, description, city_id в таблице city есть id name parent, по первому запросу можем сопоставить только по city_id и id
SELECT * FROM city WHERE id IN (SELECT DISTINCT city.parent FROM theme, city WHERE theme.city_id = city.id )
Спасибо, видать не правильно ранее выбирал, запрос долгий: Showing rows 0 - 11 (12 total, Query took 1.0308 sec) 76 сообщений, при 9000 уже Showing rows 0 - 24 (25 total, Query took 90.1977 sec)? SELECT DISTINCT city.parent FROM theme, city WHERE theme.city_id = city.id - Showing rows 0 - 11 (12 total, Query took 0.0036 sec) IN прибавляет много времени, каким то образом можно уменьшить?
не было, поставил, время упало Showing rows 0 - 11 (12 total, Query took 0.3998 sec) много это или нормально? чудеса индексы творят, где было при 9000 уже Showing rows 0 - 24 (25 total, Query took 90.1977 sec) стало Showing rows 0 - 24 (25 total, Query took 0.0067 sec)
ну это тебе решать - много или мало))) От задачи зависит. А индексы да, нужная вещь. Попробуй сделать EXPLAIN может еще чего покажет
Код (Text): id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY city ALL NULL NULL NULL NULL 480 Using where 2 DEPENDENT SUBQUERY city ref PRIMARY,parent parent 4 func 18 Using temporary 2 DEPENDENT SUBQUERY theme eq_ref city_id city_id 5 for.city.id 36 Using where; Using index не нормально? не нашел описание для Using where для Extra в справочнике
Нормально. Тут вряд ли можно что-то оптимизировать. Вариант - временная таблица, но это уже будет не один запрос, а если я не ошибаюсь 3.
SELECT t.*, c.xxx, r.xxx FROM theme t left join city as c on c.id = t.city_id left join city as r on r.id = c.parent_id WHERE t.xxx = ... И никаких подзапросов. Join-ы наше всё. Как всегда - сначала решаем, что хотим получить, потом конструируем запрос. Задача: Получить список тем с параметрами городов и регионов. Решение: (см. выше). Т.е. одновременно со списком тем получаем параметры городов и параметры регионов. Вместо xxx прописать нужные колонки/поля, повторить сколько надо. WHERE - только если необходимо ограничить выборку по темам. Если задача "Получить только список регионов, доступных в нужной теме/темах", то и запрос будет другим. п.с. Правда я не понял, как у Вас город может быть регионом(потомком) города. :/
странно выходит, проверял раз 10, везде индексы одинаковые но при 76 сообщениях время генерации больше чем при 9000 сообщениях, по логике вроде как должно быть наоборот, но в 76 сообщениях городов в 2 раза больше, возможно оно накладывает доп. время.
DISTINCT если мне память не изменяет становится причиной феерических тормозов http://www.sql.ru/articles/mssql/2005/0 ... ries.shtml
так по этому запросу SELECT DISTINCT city.parent FROM theme, city WHERE theme.city_id = city.id без DISTINCT вроде бы никак, будут выходить дубли регионов. tommyangelo походу IN сильно время оттягивает, с join выходит быстрее: Showing rows 0 - 29 (70 total, Query took 0.0046 sec) но хз как исключить дубли, DISTINCT перед SELECT не реагирует
IN не оттягивает время, оттягивает время похоже подзапрос в IN По ссылке есть решение (скорее всего). В любом случае нужно искать альтернативное решение. Я бы также советовал вам заняться профилированием и анализом запроса.
Зависит от запроса. В простых запросах, типа приведённого выше, join-ы быстрее. В подавляющем большинстве случаев join-ы лучше, чем подзапросы, на то их и придумали. Кроме того, стоит учитывать оптимизатор движка, иногда на сложных запросах он глючит и скорость падает на порядок - тогда нужен бубен и отличное знание движка, чтоб вправить ему мозги. Но это очень редко - исключение из правил. А так, join's наше всё.
такие которые исключали через distinct, здесь выводятся по много раз одни и те же города, т.е. если у нас 1000 тем с одного города, то выведется 1000 раз этот город
Если внимательно читать, то выше я писал "Если задача "Получить только список регионов, доступных в нужной теме/темах", то и запрос будет другим.". Вы уж разберитесь для начала, что Вам нужно. Список тем с параметрами городов или список городов в теме(ах).
вы наверное темы не читаете с начало? в 3 сообщение было - т.е. нужно вывести регионы, города которых есть в темах
Ну тогда и ищите регионы. Те же join's, что-то вроде: SELECT r.* FROM city r inner join city as c on c.parent_id = r.id inner join theme t on t.city_id = c.id WHERE t.xxx = ... Смысл inner тут надеюсь понятен? п.с. Кроме того, можно использовать GROUP BY с left join, если запрос небольшой. Это работает, но не красиво в плане SQL, более правильно с inner.
Конечно. Вспоминаем как работает запрос с inner: записи должны быть найдены в обоих таблицах. Описание запроса по дилетантски: Получить(select) регионы(from) id которых есть в(inner) city как(on) parent_id, а города есть в(inner) theme как(on) city_id. Эквивалент этого запроса с использованием подзапросов будет что-то вроде: SELECT r.* FROM city r where exists( select * from city c where c.parent_id = r.id and exists(select * from theme where t.city_id = c.id) ) Эффектисвность вариантов сами сравните, а потом нам расскажете.