Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Составление SQL-запросов > Объединение двух запросов


Автор: Isaev 12.11.2013, 12:16
Доброго времени суток

Делаю выборку из 1 таблицы:
Код

SELECT id, pid, title, sorting FROM `tl_page` WHERE pid=mid ORDER BY sorting

потом обхожу её в цикле и выбираю для каждой записи следующие данные(тут zid это id из первой выборки):
Код

SELECT headline, text FROM `tl_content`, `tl_article`, `tl_page` WHERE (tl_page.id=tl_article.pid AND tl_article.id=tl_content.pid AND tl_page.id=zid)


Как эти 2 зарпоса объединить в один?

Заранее благодарен

Автор: Zloxa 12.11.2013, 12:33
Цитата(Isaev @  12.11.2013,  13:16 Найти цитируемый пост)
tl_page.id=zid

заменить на pid=mid 

Автор: Isaev 12.11.2013, 12:38
Zloxa, нет, всё работает, просто я хочу 1 запросом вытаскивать все нужные данные, чтобы не нагружать лишний раз сервер, да и не громоздить в коде (просто если первый запрос возвернёт 5000 записей, потом делаю 5000 вторых запросов, что не желательно бы)
т.е. надо получить сразу id, pid, title, sorting, headline, text в ответе

и немного не так вы поняли проблемму... mid это переменная, не имеющая отношения к таблице, можете взять любую константу, например 1
zid(во избежании путаницы, т.к. во втором запросе тоже есть id) это тоже переменная, которая равна id из первого запроса на каждом этапе обхода его курсором например

Автор: Isaev 12.11.2013, 12:53
Zloxa, а точно, работает! не думал что так просто, спасибо большое!

Автор: Zloxa 12.11.2013, 12:53
Цитата(Isaev @  12.11.2013,  13:38 Найти цитируемый пост)
 получить сразу id, pid, title, sorting, headline, text в ответе

Пропишите их в селектлисте.

Цитата(Isaev @  12.11.2013,  13:38 Найти цитируемый пост)
немного не так вы поняли проблемму..

Это вы не правильно поняли, что я вам предложил.
Подумайте еще раз.

Код

SELECT headline, text 
  ,tl_page.id, tl_page.pid, tl_page.title, tl_page.sorting
FROM `tl_content`, `tl_article`, `tl_page` WHERE (tl_page.id=tl_article.pid AND tl_article.id=tl_content.pid AND tl_page.pid=mid
order by tl_page.sorting

Автор: Isaev 12.11.2013, 13:19
Zloxa,  есть только один не приятный момент)
если при "втором" запросе ничего не находится для данного id, то то, что было в первом должно бы оставаться, просто с пустыми полями headline, text
а в данном случае оно, естественно отсеивается
это возможно поправить? думаю там что-то типа JOIN надо использовать

Автор: baldina 12.11.2013, 13:40
Код

LEFT JOIN tl_article ON tl_page.id=tl_article.pid

Автор: Akina 12.11.2013, 13:41
Не типа, а именно JOIN. Причём LEFT JOIN. Причём явно указать порядок связывания таблиц - во избежание.

Автор: Isaev 12.11.2013, 14:35
не выходит что-то... извиняюсь конечно, что туплю... всё конечно просто, когда штудировал sql щёлкал тоже как орешки, но давно это было
Цитата(Akina @  12.11.2013,  13:41 Найти цитируемый пост)
Причём явно указать порядок связывания таблиц

Порядок да, не указал я выше нигде... порядок следующий:
`tl_page`основная таблица, откуда берем (id, pid, title, sorting) для результирующей
`tl_article`просто для связи `tl_page` и `tl_content`, там только id и pid
`tl_content` отсюда берём headline, text, если есть соответствие, иначе оставляем эти поля пустыми

Автор: Zloxa 12.11.2013, 14:42
Цитата(Isaev @  12.11.2013,  15:35 Найти цитируемый пост)
не выходит что-то

Вы тщательнее, тщательнее тужтесь. smile

http://segfault.kiev.ua/smart-questions-ru.html#grovelling

Автор: Akina 12.11.2013, 14:45
Цитата(Isaev @  12.11.2013,  15:35 Найти цитируемый пост)
Порядок да, не указал я выше нигде... порядок следующий:
`tl_page`основная таблица, откуда берем (id, pid, title, sorting) для результирующей
`tl_article`просто для связи `tl_page` и `tl_content`, там только id и pid
`tl_content` отсюда берём headline, text, если есть соответствие, иначе оставляем эти поля пустыми 

Значит, или 
(tl_page INNER JOIN tl_article) LEFT JOIN tl_content
или
(tl_article INNER JOIN tl_page) LEFT JOIN tl_content
А если оптимизатор настолько "умный", что сперва раскроет скобки, а потом про них забудет - то вообще придётся первое связывание выполнять в подзапросе. UPD: фигня, у нас одно левое связывание.

Автор: Zloxa 12.11.2013, 14:55
Цитата(Akina @  12.11.2013,  15:45 Найти цитируемый пост)
или 

Цитата(Akina @  12.11.2013,  15:45 Найти цитируемый пост)
или

Если пилить подобие цикла из топикстарта, то page left join (article inner join context)
Но мне кажется усложнение тут излишним. Для начало следовало бы исследовать неприемлимость тупого лефджойна всего прочего к пейджу. Скорее всего он допустим. Разница всплывет лишь в случае неуникальности неконсистентной связи в артиклях.

Автор: Isaev 12.11.2013, 15:03
Цитата(Zloxa @  12.11.2013,  14:42 Найти цитируемый пост)
http://segfault.kiev.ua/smart-questions-ru.html#grovelling

не, не smile я честно убил очередной час
да и для моей задачи и мой вариант годится, там выбока не большая... Просто врождённая слабость к оптимизациям)

Цитата(Zloxa @  12.11.2013,  14:55 Найти цитируемый пост)
Разница всплывет лишь в случае неуникальности неконсистентной связи в артиклях.

её скорее всего тоже нету

т.е. вложенного SELECT тут не будет? почему-то я к нему прихожу постоянно

Автор: Zloxa 12.11.2013, 15:09
Цитата(Isaev @  12.11.2013,  16:03 Найти цитируемый пост)
т.е. вложенного SELECT тут не будет?

Если в артикле не содержится "подвисших" записей, то вложенный селект не нужен.

Если в артикле пара id,pid ункальна, вложенный селект не нужен.

Если я правильно понял структуру даннных и данные в этой структуре целостны, то оба вышеперечисленных условия должны выполняться. 

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

Добавлено @ 15:19
Цитата(Isaev @  12.11.2013,  16:03 Найти цитируемый пост)
не, не  я честно убил очередной час

Именно что убили. Вы не показали ничего, к чему пришли в течении часа. Вы не рассказали что именно у вас не получается и не показали какой дорогой пошли. Это наводит на мысли что вы бы предпочли чтобы вас не направляли в нужную сторону, а тупо сделали бы за вас вашу работу.
Цитата(Isaev @  12.11.2013,  16:03 Найти цитируемый пост)
да и для моей задачи и мой вариант годится

А это объясняет - почему у вас отсутствует желание разбиратсья с элементарнейшими основами. smile 
Если вас не заботит результат, от чего он должен заботить кого-то другого? smile

Автор: Isaev 12.11.2013, 15:32
Цитата(Zloxa @  12.11.2013,  15:09 Найти цитируемый пост)
Вы не показали ничего, к чему пришли в течении часа. 


Код

SELECT tl_page.id, tl_page.pid, tl_page.title, headline, text FROM tl_page INNER JOIN (tl_article LEFT JOIN tl_content ON tl_article.id=tl_content.pid) ON tl_page.id=tl_article.pid


пока возвращает слишком много лишнего

Автор: Akina 12.11.2013, 15:47
Isaev, внимательно... 
Нет, не так. 
ВНИМАТЕЛЬНО перечитайте ещё раз всю тему. Чем ближе к концу, тем внимательнее.

Автор: Zloxa 12.11.2013, 16:12
Короче, тему пора закрывать:
Код

SELECT tl_page.id, tl_page.pid, tl_page.title, headline, text
FROM `tl_page`
left join `tl_article` on tl_page.id=tl_article.pid 
left join `tl_content` on tl_article.id=tl_content.pid
where tl_page.pid=mid

либо, если в артикле есть "битые" ссылки на контент, чтобы получить аналог с топикстартом:

Код

SELECT tl_page.id, tl_page.pid, tl_page.title, headline, text
FROM `tl_page`
left join ( select  headline, text, tl_article.pid 
  from `tl_article` 
  inner join `tl_content` on tl_article.id=tl_content.pid
) as s on s.pid = tl_page.id
where tl_page.pid=mid


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

Автор: Akina 12.11.2013, 16:23
Тогда уж лучше добавить доп. условие в первый вариант и отсечь зависший контент 
Код

where not(tl_article.id  is null and tl_content.pid is not null)

Автор: Zloxa 12.11.2013, 16:23
Цитата(Zloxa @  12.11.2013,  17:12 Найти цитируемый пост)
 если в артикле есть "битые" ссылки на контен

пожалуй, можно еще отфильтровать их добавив в where первого запроса. Наверное как-то так:
Код

and (tl_content.pid is not null or tl_article.pid is null)

Автор: Akina 12.11.2013, 16:24
Zloxa,  smile 

Автор: Zloxa 12.11.2013, 17:27
Akina, где-то мы с тобой расходимся, кто-то из нас накосячил. По закону де моргана у нас с тобой должны бы быть инверсными предикаты.

Я вот даже табличку истинности набросал, но чот не могу сообразить кто же накосячив. Моя предвзятость меня склоняет к мнению, что я скорее более прав, но что-то не позволяет склониться к этому мнению уверенно.
Код

article  content  not(article is null and content is not null)  (article is null or content is not null )
null      null                     true                                 true
not null  null                     true                                 false
null      not null                 false                                true
not null  not null                 true                                 true

Мне кажется ты отфильтровываешь тот кейс, который невер бин хаппенд.

Цитата(Akina @  12.11.2013,  17:23 Найти цитируемый пост)
tl_article.id

и это. Здесь лучше пид. Если id nullable, а произошел джойн по пиду...

Автор: Akina 12.11.2013, 18:45
Цитата(Zloxa @  12.11.2013,  18:27 Найти цитируемый пост)
Здесь лучше пид

Это опечатка :(

Цитата(Zloxa @  12.11.2013,  18:27 Найти цитируемый пост)
Мне кажется ты отфильтровываешь тот кейс, который невер бин хаппенд.

Я фильтрую подвисший текст. Т.е. контент есть, а статьи к нему нет. КАжется...

Автор: Zloxa 12.11.2013, 21:47
Цитата(Akina @  12.11.2013,  19:45 Найти цитируемый пост)
 Т.е. контент есть, а статьи к нему нет.

C учетом того, что контент тут подтягивается через артикль, это не существующий кейс ))

Автор: Isaev 13.11.2013, 10:33
Zloxa, взял второй вариант на всякий случай, хотя первый справляется так же, видимо кривых данных нет (ну пока по крайней мере), но т.к. за них отвечаю не я, лучше подстраховаться

Спасибо, ребята! Большое и человеческое

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)