Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Left join not in 
:(
    Опции темы
gelo86
Дата 28.9.2009, 19:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 388
Регистрация: 26.10.2007

Репутация: нет
Всего: нет



Допустим у меня есть две таблицы: 
Код

  User(id) / Read_books(user_id, book_name).


Есть такие записи:
Код

User     Read_books
1           1,   'Name1'
2           1,   'Name2'
3           2,   'Name3'


Как мне вытенуть людей, каторие нечитали книжки с именем Name2 ? Left join мне вернет человека с id=1, так как он имеет есчо запись с книжкой под названием 'Name1'.




PM MAIL   Вверх
ТоляМБА
Дата 28.9.2009, 19:30 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Котэ
***


Профиль
Группа: Завсегдатай
Сообщений: 1607
Регистрация: 15.12.2004

Репутация: 4
Всего: 252



Методом исключения:

Код
Select *
From User
where user.id not in
(select Read_books.user_id
from Read_books
where book_name='Name2')


Если не пойдет, то после закрывающей скобки допиши 'AS a'.

PM   Вверх
gelo86
Дата 28.9.2009, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 388
Регистрация: 26.10.2007

Репутация: нет
Всего: нет



1. У меня около 30000 людей, и если половина из них прочитали ету книжку, то получится что в not in будет около 15000 идишников (а как слишал not in при таких количествах неочень оптимальный).

2. Да и селект : 
Код
select Read_books.user_id from Read_books where book_name='Name2'
 небудет выполняться для каждого человека 
Код
Select * From User where user.id not in
 ?

Это сообщение отредактировал(а) gelo86 - 28.9.2009, 19:34
PM MAIL   Вверх
Zloxa
Дата 28.9.2009, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161




M
Zloxa
Перенесено из баз данных



--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Gluttton
Дата 28.9.2009, 19:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: 24
Всего: 54



Код

select id
from user
    inner join read_books
    on user.id=read_books.user_id
    where read_books.user_id not in
    (
        select distinct user_id
        from read_books
            where book_name='Name2'
    )



--------------------
Слава Україні!
PM MAIL   Вверх
gelo86
Дата 28.9.2009, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 388
Регистрация: 26.10.2007

Репутация: нет
Всего: нет



Цитата(Gluttton @ 28.9.2009,  19:37)
Код

select id
from user
    inner join read_books
    on user.id=read_books.user_id
    where read_books.user_id not in
    (
        select distinct user_id
        from read_books
            where book_name='Name2'
    )

Та же проблема с not in. Я понемаю, что может и нету другого способа. А как ви относитесь к: not in(1..15000) ?
PM MAIL   Вверх
Gluttton
Дата 28.9.2009, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: 24
Всего: 54



СУБД? Например счастливые пользователи Oracle могут воспользоваться предложением MINUS...


--------------------
Слава Україні!
PM MAIL   Вверх
gelo86
Дата 28.9.2009, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 388
Регистрация: 26.10.2007

Репутация: нет
Всего: нет



Исползуется Oracle, но пишем на Java + Hibernate => HQL, поетому думаю MINUS в HQL непрокатит :(
PM MAIL   Вверх
boevik
Дата 28.9.2009, 19:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1452
Регистрация: 31.5.2004
Где: Израиль

Репутация: нет
Всего: 35



Можно конечно совсем без not in, 
Код

select t1.id from user t1 left join
(select user_id from read_books where name = 'book1') t2
on t1.id =t2.user_id
where t2.user_id is null





--------------------
Никогда не говори никогда
PM MAIL WWW   Вверх
gelo86
Дата 28.9.2009, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 388
Регистрация: 26.10.2007

Репутация: нет
Всего: нет



Цитата(boevik @ 28.9.2009,  19:49)
Можно конечно совсем без not in, 
Код

select t1.id from user t1 left join
(select user_id from read_books where name = 'book1') t2
on t1.id =t2.user_id
where t2.user_id is null

А СУБД внутренний селект будет виполнять толко один раз ?
PM MAIL   Вверх
Gluttton
Дата 28.9.2009, 19:58 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: 24
Всего: 54



Вот тут  написано про про разность и некоторые варианты его реализации...


--------------------
Слава Україні!
PM MAIL   Вверх
boevik
Дата 28.9.2009, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1452
Регистрация: 31.5.2004
Где: Израиль

Репутация: нет
Всего: 35



Цитата(gelo86 @  28.9.2009,  19:53 Найти цитируемый пост)

А СУБД внутренний селект будет виполнять толко один раз ? 

Да, так как не зависит от внешних параметров.


--------------------
Никогда не говори никогда
PM MAIL WWW   Вверх
Zloxa
Дата 28.9.2009, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



boevik, 
Тогда уж лучше
Код

select /*distinct*/ t1.id 
  from user t1 
  left join read_books t2 on name = 'book1' and t1.id =t2.user_id
where t2.user_id is null

disitnct раскоментировать, если пара user_id,name не уникальна.

ну и еще несколько вариаций
Код

select * from user where not exists (select null from read_books where read_books.user_id = user.id and name = 'book1')

select id from user
minus
select user_id from read_books where name = 'book1'

select * from user where id in (select user_id from user_books where name != 'book1')


Цитата(gelo86 @  28.9.2009,  19:32 Найти цитируемый пост)
а как слишал not in при таких количествах неочень оптимальный

Веский аргумент. smile 


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
gelo86
Дата 28.9.2009, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 388
Регистрация: 26.10.2007

Репутация: нет
Всего: нет



Для чего нужен: 
Цитата(Zloxa @  28.9.2009,  20:08 Найти цитируемый пост)
where t2.user_id is null
 ?

PM MAIL   Вверх
boevik
Дата 28.9.2009, 20:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1452
Регистрация: 31.5.2004
Где: Израиль

Репутация: нет
Всего: 35



Цитата(Zloxa @  28.9.2009,  20:08 Найти цитируемый пост)
Тогда уж лучше

Код

select /*distinct*/ t1.id 
  from user t1 
  left join read_books t2 on name = 'book1' and t1.id =t2.user_id
where t2.user_id is null

disitnct раскоментировать, если пара user_id,name не уникальна.

Вполне возможно что и этот вариант пройдет. (не совсем помню как поведет себя name = 'book1' внутри on)

Цитата(Zloxa @  28.9.2009,  20:08 Найти цитируемый пост)
Код

select * from user where not exists (select null from read_books where read_books.user_id = user.id and name = 'book1')

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

Цитата(Zloxa @  28.9.2009,  20:08 Найти цитируемый пост)
Код

select id from user
minus
select user_id from read_books where name = 'book1'

минус не все СУБД поддерживают.



Цитата(Zloxa @  28.9.2009,  20:08 Найти цитируемый пост)
Код

select * from user where id in (select user_id from user_books where name != 'book1')

совсем не верный результат вернет.

Добавлено через 8 минут и 13 секунд
Цитата(gelo86 @ 28.9.2009,  20:11)
Для чего нужен: 
Цитата(Zloxa @  28.9.2009,  20:08 Найти цитируемый пост)
where t2.user_id is null
 ?

показать только теx пользователей из t1 которые не присуствуют в t2


--------------------
Никогда не говори никогда
PM MAIL WWW   Вверх
Zloxa
Дата 28.9.2009, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(boevik @  28.9.2009,  20:30 Найти цитируемый пост)
совсем не верный результат вернет.

Да, виноват. Спасибо.

Цитата(boevik @  28.9.2009,  20:30 Найти цитируемый пост)
В этом случае на каждую запись в таблице user выполняется внутрений select, если есть индекс то может и не страшно, а если нет, то ...

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

Если есть ограничение уникальности по паре (user_id,name), то дистинкт не нужен, но и индекс есть. Если мы используем индекс, то для левого джоина ли, для анти джоина ли, разницу сложно будет измерить существующими в настоящее время приборами.

как бы в общем случае, этот вариант предпочтительнее левого джойна.(для оракла)

Но далеко не факт что он предпочтительнее not in. Мне кажется весьма вероятным, что замена not in ни на left join ни на not exists ничего ТС не даст.

Цитата(boevik @  28.9.2009,  20:30 Найти цитируемый пост)
минус не все СУБД поддерживают.

ТС озвучил целевую платформу.
Кстати, буде у ТС записей порядка на три-четыре поболе, я бы настаивал на том, чтобы он присмотрелся именно к этому варианту.

boevik, Вообще я повторил ошибку, которую допускаю часто. Первую часть поста я обращал тебе. Остальную часть - ТС. Опять забыл поставить обращение, прошу прощения. Я не думал тебе оппонировать, просто убрал из твоего варианта лишние скобки, какбы подтверждая его правильность..



Это сообщение отредактировал(а) Zloxa - 28.9.2009, 21:57


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
DimW
Дата 29.9.2009, 08:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1330
Регистрация: 24.2.2005
Где: Орёл

Репутация: 4
Всего: 44



Цитата(Zloxa @  28.9.2009,  21:34 Найти цитируемый пост)
ТС озвучил целевую платформу.


Zloxa, вся мега платформа ТС огрничена использованием  HQL - это диалект всеми любимого и нелюбимого ORM.
так что будь у него хоть супер пупер СУБД толку от нее НОЛЬ!


PM MAIL ICQ   Вверх
Zloxa
Дата 29.9.2009, 08:36 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(DimW @  29.9.2009,  08:17 Найти цитируемый пост)
HQL 

Надо б разобраться с этой байдой.. хотябы  в терминологии. Дабы впредь не вестись :(

Это сообщение отредактировал(а) Zloxa - 29.9.2009, 08:37


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
DimW
Дата 29.9.2009, 09:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1330
Регистрация: 24.2.2005
Где: Орёл

Репутация: 4
Всего: 44



Цитата(Zloxa @  29.9.2009,  08:36 Найти цитируемый пост)
Надо б разобраться с этой байдой

гугль по ключивому слову - Hibernate

Цитата(Zloxa @  29.9.2009,  08:36 Найти цитируемый пост)
байдой

 smile в яблочко
PM MAIL ICQ   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.0635 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.