Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MySQL > Выборка из 2х таблиц


Автор: AnemoN 10.12.2009, 09:14
Есть две таблицы names и names_used

names
nid    name
---     ---
1       vasya
2       kolya
3       petya
4       vanya

names_used
nid    pid
---     ---
1       2
3       2

Необходимо составить запрос, который вернет names.nid, names.name, т.о. что не существует names_used.nid = names.nid или существует, но names_used.pid!=x

Автор: Gluttton 10.12.2009, 09:37
ПисАл на коленке, возможно будут ошибки.
Код

select
    s.nid,
    s.name
from
(
    select
        n.nid,
        n.name,
        nu.nid as nidu,
        nu.pid
    from 
        names as n
        left join names_used as nu
        on n.nid=nu.nid
)   as s
    where s.nidu is null
    or s.pid<>x

Автор: AnemoN 10.12.2009, 09:44
Большое вам спасибо, код идеально работает

Автор: DimW 10.12.2009, 09:52
так что ли:
Код

select * 
  from names n
 where not exists (select * from names_used nu where nu.nid = n.nid)  
union all
select n.* 
  from names n
      ,names_used nu
 where nu.nid = n.nid
   and nu.pid != :x

Автор: Zloxa 10.12.2009, 10:04
Цитата(Gluttton @  10.12.2009,  09:37 Найти цитируемый пост)
ПисАл на коленке, возможно будут ошибки.

а подзапрос зачем?
Код

    select
        n.nid,
        n.name,
    from 
        names as n
    left join names_used as nu
       on n.nid=nu.nid
    where nu.nid is null
         or nu.pid = :x


Автор: Gluttton 10.12.2009, 10:24
Zloxa, 
Цитата(Zloxa @  10.12.2009,  10:04 Найти цитируемый пост)
а подзапрос зачем?

Боялся, что не правильно таблицы соединятся (на работу торопился smile )...

AnemoN, 
Цитата(AnemoN @  10.12.2009,  09:44 Найти цитируемый пост)
Большое вам спасибо, код идеально работает

Не за что, только я ошибся и вместо неравенства с переменной поставил критерий на равенство smile ...

DimW, 
Цитата(DimW @  10.12.2009,  09:52 Найти цитируемый пост)
так что ли:

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

Автор: DimW 10.12.2009, 10:34
Цитата(Gluttton @  10.12.2009,  10:24 Найти цитируемый пост)
но думаю, что предложенный тобою вариант будет выполняться дольше чем мой. 

грохнул уже  smile smile

Автор: Zloxa 10.12.2009, 10:40
Цитата(DimW @  10.12.2009,  10:34 Найти цитируемый пост)
грохнул уже

Зачем???... правильный ведь вариант был.
А то что оптимизатор еще не способен нормальный план для такого выражения составить - то ж косяки оптимизатора.
SQL - декларативный язык. Он выражает мысль(цель) но не методы(средства) ее реализации. smile
за то он мне и люб smile

Автор: DimW 10.12.2009, 10:57
Цитата(Zloxa @  10.12.2009,  10:40 Найти цитируемый пост)
Он выражает мысль(цель) но не методы(средства) ее реализации.

мда, не хорошо получилось, ща подредактирую... smile

Автор: AnemoN 10.12.2009, 11:45
Цитата(Gluttton @  10.12.2009,  10:24 Найти цитируемый пост)
не уверен, но думаю, что предложенный тобою вариант будет выполняться дольше чем мой. 


Сейчас проверил оба запроса к бд - результаты неоднозначные.

При 65.000 записей в names - ваш запрос быстрее.
При 30.000 записей в names - медленнее.

Если к запросам добавить ORDER BY rand() - все меняется.

Сейчас сижу и думаю где, что и как в конфиге сервера подкрутить, чтобы этот запрос быстрее выполнялся, т.к. из-за него скорость работы программы упала в 2-3 раза smile

Автор: Zloxa 10.12.2009, 11:52
Цитата(AnemoN @  10.12.2009,  11:45 Найти цитируемый пост)
чтобы этот запрос быстрее выполнялся

Да, поиск по невхождению да неравенству - емок ;)
При проектировании таких поисков лучше б избегать.

Автор: Akina 10.12.2009, 12:41
Цитата(AnemoN @  10.12.2009,  12:45 Найти цитируемый пост)
Сейчас проверил оба запроса к бд 

А какие индексы на таблицах? а какие индексы используются? лучше бы вместо абстрактного быстрее/медленнее дал бы планы запросов. И полные структуры таблиц. Тогда это было бы показательно.

Автор: Zloxa 10.12.2009, 13:44
Akina, какие индексы могут быть использованы при отборе по неравенству?  smile 

Разве что джойн......

Но джойн по индексу тоже не выгодным должен быть, потому как мы полностью сканируем обе таблицы, а так еще и индекс придется полностью сканировать.

Автор: Akina 10.12.2009, 14:19
А где http://forum.vingrad.ru/index.php?showtopic=283279&view=findpost&p=2042660 отбор по неравенству? и что потребует сканирования таблицы?

Автор: Gluttton 10.12.2009, 14:32
Цитата(Akina @  10.12.2009,  14:19 Найти цитируемый пост)
А где тут отбор по неравенству?


Цитата(AnemoN @  10.12.2009,  09:14 Найти цитируемый пост)
Необходимо составить запрос, который вернет names.nid, names.name, т.о. что не существует names_used.nid = names.nid или существует, но names_used.pid!=x


Цитата(AnemoN @  10.12.2009,  09:44 Найти цитируемый пост)
Большое вам спасибо, код идеально работает


Цитата(Gluttton @  10.12.2009,  10:24 Найти цитируемый пост)
Не за что, только я ошибся и вместо неравенства с переменной поставил критерий на равенство  ...


Я свой запрос уже подправил smile ...

Автор: Zloxa 10.12.2009, 14:47
Цитата(Akina @  10.12.2009,  14:19 Найти цитируемый пост)
тут 

Gluttton уже ответил... я ошибся, указав равенство.

Цитата(Akina @  10.12.2009,  14:19 Найти цитируемый пост)
и что потребует сканирования таблицы

Даже если мы оставим равенство, полного сканирования обоих таблиц потребует отбор по is null smile

Автор: AnemoN 11.12.2009, 04:35
=x я сразу заметил и заменил на !=x, все-таки базовые навыки составления запросов у меня имеются.

Цитата(Akina @  10.12.2009,  12:41 Найти цитируемый пост)
А какие индексы на таблицах? а какие индексы используются? лучше бы вместо абстрактного быстрее/медленнее дал бы планы запросов. И полные структуры таблиц. Тогда это было бы показательно. 

Это всего-лишь "быстый" тест, на полноценное тестирование не претендующий.

Кстати, не вдаваясь в подробности, самым производительным вариантом для меня оказывается отдельная таблица namesX для каждого рабочего профиля программы.
Правда это больше смахивает на извращение, но помимо скорости есть еще одно важное преимущество - винт так жутко не кряхтит во время выполнения запроса и не мешает спать =)
Поэтому, пока не смогу оптимизировать запрос, оставлю такой вариант.

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