Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 31.07.09 13:32
Оценка:
Есть таблица A. Надо выбрать из нее все записи, на которые есть ссылки в таблицах B и C.
То есть, простейшее решение выглядит так:
select A.* from A inner join B on B.a = A.a
union
select A.* from A inner join C on C.a = A.a

Но мне надо, чтобы селект был только один, причем таблицы в запрос могут добавляться только через join'ы.
Эти ограничения накладывает Hibernate Criteria API. Я сначала составляю Criteria, который является обвязкой запроса, потом отдаю его, и запросивший этот Criteria может добавить еще условия по своему выбору.
В общем, можно как-либо сделать один селект через джойны заместо нескольких селектов с union?
union join
Re: Можно ли заменить UNION на какой-нибудь JOIN?
От: Romanzek Россия  
Дата: 31.07.09 13:54
Оценка:
Здравствуйте, Donz, Вы писали:

D>Есть таблица A. Надо выбрать из нее все записи, на которые есть ссылки в таблицах B и C.

D>То есть, простейшее решение выглядит так:
D>select A.* from A inner join B on B.a = A.a
D>union
D>select A.* from A inner join C on C.a = A.a

D>Но мне надо, чтобы селект был только один, причем таблицы в запрос могут добавляться только через join'ы.

D>Эти ограничения накладывает Hibernate Criteria API. Я сначала составляю Criteria, который является обвязкой запроса, потом отдаю его, и запросивший этот Criteria может добавить еще условия по своему выбору.
D>В общем, можно как-либо сделать один селект через джойны заместо нескольких селектов с union?

B и C? Или B ИЛИ C?
Re: Можно ли заменить UNION на какой-нибудь JOIN?
От: cvetkov  
Дата: 31.07.09 14:51
Оценка: 4 (1) -1
Здравствуйте, Donz, Вы писали:

D>Есть таблица A. Надо выбрать из нее все записи, на которые есть ссылки в таблицах B и C.

D>То есть, простейшее решение выглядит так:
D>select A.* from A inner join B on B.a = A.a
D>union
D>select A.* from A inner join C on C.a = A.a

select A.* from A. left join B on B.a = A.a left join C on C.a = A.a
where notNull(B.a) and notNull(C.a)

не помню как на null проверять
... << RSDN@Home 1.2.0 alpha 4 rev. 1227>>
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Romanzek Россия  
Дата: 31.07.09 15:09
Оценка: 8 (1)
Здравствуйте, cvetkov, Вы писали:

C>Здравствуйте, Donz, Вы писали:


D>>Есть таблица A. Надо выбрать из нее все записи, на которые есть ссылки в таблицах B и C.

D>>То есть, простейшее решение выглядит так:
D>>select A.* from A inner join B on B.a = A.a
D>>union
D>>select A.* from A inner join C on C.a = A.a

C>select A.* from A. left join B on B.a = A.a left join C on C.a = A.a

C>where notNull(B.a) and notNull(C.a)

C>не помню как на null проверять


В данном случае проще написать
select A.* from A. join B on B.a = A.a join C on C.a = A.a
Результат будет тот же. Это работает для случая B и C, причем полным эквивалентом union будет не всегда — если в таблицах B или С есть несколько ссылок на A, то будет замножение результата. Нужен distinct или group by.

Для случая B ИЛИ C нужно писать
select distinct(A.a) from A left join B on B.a = A.a left join C on C.a = A.a
where B.a is not null or C.a is not null
Re: Можно ли заменить UNION на какой-нибудь JOIN?
От: elmal  
Дата: 31.07.09 15:41
Оценка:
Здравствуйте, Donz, Вы писали:

D>В общем, можно как-либо сделать один селект через джойны заместо нескольких селектов с union?

Не знаю, правильно ли, но я последний раз делал так — (сразу на HQL, специально открыл исходники, на перфоманс вроде жалоб нет)
select A.* from A where (A.id in (select A1.id from A1 join A1.b B) or A.id in (select A2.id from A2 join A2.c C) ).


У меня joinов было 6, таким образом заработало гораздо шустрее, чем в случае с left join (тогда жалобы были на перфоманс ).
Когда-то кажется делал другим способом, и кажется без in, но напрочь забыл, и это осталось в другом проекте:
что-то вроде
select A.* from A, A join A.b B, A join A.c C where A.id=B.id or A.id=C.id

Увы, запросы я много писал более 4-х лет назад, сейчас один запрос в полгода максимум.
Re: Можно ли заменить UNION на какой-нибудь JOIN?
От: svanir Украина  
Дата: 31.07.09 16:25
Оценка:
Здравствуйте, Donz, Вы писали:

D>Есть таблица A. Надо выбрать из нее все записи, на которые есть ссылки в таблицах B и C.

D>То есть, простейшее решение выглядит так:
D>select A.* from A inner join B on B.a = A.a
D>union
D>select A.* from A inner join C on C.a = A.a

D>Но мне надо, чтобы селект был только один, причем таблицы в запрос могут добавляться только через join'ы.

D>Эти ограничения накладывает Hibernate Criteria API. Я сначала составляю Criteria, который является обвязкой запроса, потом отдаю его, и запросивший этот Criteria может добавить еще условия по своему выбору.
D>В общем, можно как-либо сделать один селект через джойны заместо нескольких селектов с union?

А почему нельзя так:
select A.* from A inner join B on B.a = A.a
inner join C on C.a=A.a
?
и почему Вы берете "все" только из А?
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: elmal  
Дата: 31.07.09 17:32
Оценка: +1
Здравствуйте, svanir, Вы писали:

S>А почему нельзя так:

S>select A.* from A inner join B on B.a = A.a
S> inner join C on C.a=A.a
S>?
S>и почему Вы берете "все" только из А?
Здесь тогда будет не объединение, а пересечение. И условие — нужно показать все A, которые связаны либо с B, либо с C. Достаточно типичная задача кстати.
Re: Можно ли заменить UNION на какой-нибудь JOIN?
От: Lloyd Россия  
Дата: 31.07.09 17:53
Оценка: 8 (1)
Здравствуйте, Donz, Вы писали:

D>В общем, можно как-либо сделать один селект через джойны заместо нескольких селектов с union?


SELECT A.*
FROM A
LEFT JOIN B ON B.a = A.a
LEFT JOIN C ON C.a = A.a
WHERE (B.a IS NOT NULL) OR (C.a IS NOT NULL)
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: elmal  
Дата: 31.07.09 18:22
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>
L>SELECT A.*
L>FROM A
L>LEFT JOIN B ON B.a = A.a
L>LEFT JOIN C ON C.a = A.a
L>WHERE (B.a IS NOT NULL) OR (C.a IS NOT NULL)
L>

По крайней мере на MS SQL 2005 тормоза наблюдал страшные (20 секунд запрос выполнялся), сойдет только на небольших объемах. Сервер похоже сначала таблицы соединит (а они черти какого объема), а только потом фильтрует — жуть.
Re: Можно ли заменить UNION на какой-нибудь JOIN?
От: Lloyd Россия  
Дата: 31.07.09 20:55
Оценка: 1 (1)
Здравствуйте, Donz, Вы писали:

D>Эти ограничения накладывает Hibernate Criteria API. Я сначала составляю Criteria, который является обвязкой запроса, потом отдаю его, и запросивший этот Criteria может добавить еще условия по своему выбору.

D>В общем, можно как-либо сделать один селект через джойны заместо нескольких селектов с union?

А если создать вьюху с union-ами и использовать ее?
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 01.08.09 09:43
Оценка:
Здравствуйте, Romanzek, Вы писали:

D>>Есть таблица A. Надо выбрать из нее все записи, на которые есть ссылки в таблицах B и C.

D>>То есть, простейшее решение выглядит так:
D>>select A.* from A inner join B on B.a = A.a
D>>union
D>>select A.* from A inner join C on C.a = A.a

R>B и C? Или B ИЛИ C?


Или B, или C. В общем надо выбрать один раз все записи, ссылки на которые есть хотя бы в одной из таблиц B или C. Нужен аналог приведенного запроса
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 01.08.09 09:46
Оценка:
Здравствуйте, elmal, Вы писали:

D>>В общем, можно как-либо сделать один селект через джойны заместо нескольких селектов с union?

E>Не знаю, правильно ли, но я последний раз делал так — (сразу на HQL, специально открыл исходники, на перфоманс вроде жалоб нет)
E>
E>select A.* from A where (A.id in (select A1.id from A1 join A1.b B) or A.id in (select A2.id from A2 join A2.c C) ).
E>


E>У меня joinов было 6, таким образом заработало гораздо шустрее, чем в случае с left join (тогда жалобы были на перфоманс ).


Запрос с двумя внутренними селектами и условиями in работает быстрее left join'ов? Что-то слабо верится...
Но в любом случае подселекты не катят — мне надо все сделать через Criteria API.
Re[3]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 01.08.09 09:49
Оценка:
Здравствуйте, elmal, Вы писали:

L>>
L>>SELECT A.*
L>>FROM A
L>>LEFT JOIN B ON B.a = A.a
L>>LEFT JOIN C ON C.a = A.a
L>>WHERE (B.a IS NOT NULL) OR (C.a IS NOT NULL)
L>>

E>По крайней мере на MS SQL 2005 тормоза наблюдал страшные (20 секунд запрос выполнялся), сойдет только на небольших объемах. Сервер похоже сначала таблицы соединит (а они черти какого объема), а только потом фильтрует — жуть.

Можно подробнее? Оптимизацию запросов в БД начал изучать заново с полгода назад. Пока я в этом запросе ничего криминального не вижу.
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 01.08.09 09:53
Оценка:
Здравствуйте, Lloyd, Вы писали:

D>>Эти ограничения накладывает Hibernate Criteria API. Я сначала составляю Criteria, который является обвязкой запроса, потом отдаю его, и запросивший этот Criteria может добавить еще условия по своему выбору.

D>>В общем, можно как-либо сделать один селект через джойны заместо нескольких селектов с union?

L>А если создать вьюху с union-ами и использовать ее?


Не подходит, так как выбранные объекты могут быть изменены. С вьхой придется делать еще один мэппинг уже конкретно на таблицу и перед изменениями таскать выбранные объекты еще одним запросом с условием in. В общем, не очень красиво и захламляет код.
Плюс это повлечет изменение БД, что в моем случае несколько геморройно.
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 01.08.09 09:55
Оценка:
Здравствуйте, svanir, Вы писали:

D>>Есть таблица A. Надо выбрать из нее все записи, на которые есть ссылки в таблицах B и C.

D>>То есть, простейшее решение выглядит так:
D>>select A.* from A inner join B on B.a = A.a
D>>union
D>>select A.* from A inner join C on C.a = A.a

S>А почему нельзя так:

S>select A.* from A inner join B on B.a = A.a
S> inner join C on C.a=A.a
S>?

Этот запрос выберет записи, которые одновременно находятся и в B, и в C. Мне же надо условие "или в B, или в C". elmal уже написал, в общем.

S>и почему Вы берете "все" только из А?

Не совсем понял вопрос. Надо мне так, взять только все данные из таблицы A, а остальные таблицы нужны только для ограничения выборки.
Re[4]: Можно ли заменить UNION на какой-нибудь JOIN?
От: elmal  
Дата: 01.08.09 11:28
Оценка:
Здравствуйте, Donz, Вы писали:

D>Можно подробнее? Оптимизацию запросов в БД начал изучать заново с полгода назад. Пока я в этом запросе ничего криминального не вижу.

Да не могу подробнее, тут все от оптимизатора зависит. Я ж говорю, что пишу один более-менее сложный запрос в полгода, а оптимизация ... на одном сервере будет шустро работать так, на другом иначе — не угадаешь, а все тонкости учить для каждого сервера — не окупится, слишком часто они меняются, по крайней мере у меня. Просто вот такой запрос в случае с left join у меня узким местом оказался. Когда данных было мало, все шустро, наполнили базу — тормоза сразу страшные (а под нагрузочным тестированием вообще жуть). Переписал в итоге на вариант с in — практически моментально стало (точнее время выполнения запроса меньше времени перерисовки, соответственно дальше я отпимизировать не стал). И еще были проблемы с left join на MS SQL (его генерил hibernate), тоже одна сущность грузилась в результате несколько секунд — переписал с использованием вложенных подзапросов, сразу все шустро стало. LEFT JOIN я бы потому старался избегать, часто сервер делает сначала его, а только потом фильтрацию (мои догадки это, только этим могу тормоза объяснить).
Ну и я там еще один вариант показывал (пересечение таблицы сама с собой который), по идее он самый шустрый должен быть (я не уверен что там я буз ошибок написал), на firebird я когда пересечения вот такие делал страшные для таблиц в миллионы записей — вполне шустро работало. А in мне не очень нравится, интуиция просто подсказывает что in лучше избегать, оптимизатор может не очень хорошо построить план выполнения.
Re[3]: Можно ли заменить UNION на какой-нибудь JOIN?
От: elmal  
Дата: 01.08.09 11:41
Оценка: 8 (1)
Здравствуйте, Donz, Вы писали:

D>Запрос с двумя внутренними селектами и условиями in работает быстрее left join'ов? Что-то слабо верится...

У меня тогда этих left join было штук 6, и каждый еще соединялся еще с несколькоми таблицами (ох хотелось тогда высказать все, что я думаю о структуре базы, еле сдержался ). С in заработало быстрее, причем раз в 100 — скорость замерял.
D>Но в любом случае подселекты не катят — мне надо все сделать через Criteria API.
Нижний вариант пробовал? Он явно должен быть самым шустрым, так как там только join по первичному ключу идет (я правда не знаю, можно ли через Criteria API пересечения таблиц как я указал делать). Возможно я ошибся, и я что-то забыл в запросе, надо пробовать, но один раз у меня точно похожим образом union на хибернейте сделать получилось.
Re[4]: Можно ли заменить UNION на какой-нибудь JOIN?
От: elmal  
Дата: 01.08.09 11:49
Оценка:
Здравствуйте, elmal, Вы писали:

E>У меня тогда этих left join было штук 6, и каждый еще соединялся еще с несколькоми таблицами (ох хотелось тогда высказать все, что я думаю о структуре базы, еле сдержался ). С in заработало быстрее, причем раз в 100 — скорость замерял.

Хотя, справедливости ради, запрос у меня был несколько посложнее, там у меня была задача похожая на твою, но там связи были по простым аттрибутам, которые с таблицей B были связана еще через 5 таблиц . Они не были даже внешними ключами и на них даже индексов не висело, потому и такой результат. Потом индексы добавили, я попросил того, кто занимается оптимизацией предыдущий запрос проверить, вроде один черт left join медленнее чем вложенные селекты с in оказалось.
Re[4]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 01.08.09 17:27
Оценка:
Здравствуйте, elmal, Вы писали:

D>>Запрос с двумя внутренними селектами и условиями in работает быстрее left join'ов? Что-то слабо верится...

E>У меня тогда этих left join было штук 6, и каждый еще соединялся еще с несколькоми таблицами (ох хотелось тогда высказать все, что я думаю о структуре базы, еле сдержался ). С in заработало быстрее, причем раз в 100 — скорость замерял.
D>>Но в любом случае подселекты не катят — мне надо все сделать через Criteria API.
E>Нижний вариант пробовал? Он явно должен быть самым шустрым, так как там только join по первичному ключу идет (я правда не знаю, можно ли через Criteria API пересечения таблиц как я указал делать). Возможно я ошибся, и я что-то забыл в запросе, надо пробовать, но один раз у меня точно похожим образом union на хибернейте сделать получилось.

Нижний — это left join и проверка на null? Пока нет, пробовать буду в понедельник.
За информацию спасибо, буду проверять, так как запрос будет очень часто исполняемым.
Re[5]: Можно ли заменить UNION на какой-нибудь JOIN?
От: elmal  
Дата: 01.08.09 18:30
Оценка:
Здравствуйте, Donz, Вы писали:

D>Нижний — это left join и проверка на null? Пока нет, пробовать буду в понедельник.

Я вариант с left join вообще не приводил. Он работать то будет, тут я не сомневаюсь, вопрос в скорости. Второй вариант, который я предложил — пересечение таблицы и двумя джоинами, как любят ораклисты писать (не джоин, а select from A,B,C where ... ) вот он очень шустро должен выполняться теоретически, возможно даже шустрее, чем в случае с использованием union (неисповедимы пути оптимизатора запросов).
Еще раз —
select A.* from A, A join A.b B, A join A.c C where A.id=B.id or A.id=C.id

Вот только не факт, что я его правильно написал, но один раз я точно что-то подобное проворачивал на хибернейте, помню точно, что я делал union и без left join, и без in, и основная идея была именно такая — пересечение таблицы с собой под разными алиасами (задача была другой помнится). Просьба попробовать, и сообщить, если получится — я тогда в следующий раз, когда это понадобится, поиском найду, а то опять забуду . На деле, синтаксис SQL весьма избыточен, и при желании одним запросом можно сделать многое, даже если куча фичь, вроде union, вложенных подзапросов и т.д не поддерживается.
Re[6]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 02.08.09 09:35
Оценка:
Здравствуйте, elmal, Вы писали:

E>
E>select A.* from A, A join A.b B, A join A.c C where A.id=B.id or A.id=C.id
E>

E>Вот только не факт, что я его правильно написал, но один раз я точно что-то подобное проворачивал на хибернейте, помню точно, что я делал union и без left join, и без in, и основная идея была именно такая — пересечение таблицы с собой под разными алиасами (задача была другой помнится). Просьба попробовать, и сообщить, если получится — я тогда в следующий раз, когда это понадобится, поиском найду, а то опять забуду .

Сейчас под рукой даже парсера нет, но подозреваю, что ошибка в синтаксисе будет. Да и вообще не очень понял смысл запроса. У A нет информации о таблицах B и C. B, C могут связаться с A только по идентификатору из A и все. Откуда поля A.b, A.c?
Хитропопые маппинге с алиасами на саму себя уже есть, правда, для других целей.
Re[7]: Можно ли заменить UNION на какой-нибудь JOIN?
От: elmal  
Дата: 02.08.09 10:20
Оценка:
Здравствуйте, Donz, Вы писали:

D>Сейчас под рукой даже парсера нет, но подозреваю, что ошибка в синтаксисе будет. Да и вообще не очень понял смысл запроса. У A нет информации о таблицах B и C. B, C могут связаться с A только по идентификатору из A и все. Откуда поля A.b, A.c?

A.b это если на sql перевести A inner join B on A.id=B.id. Я просто привык уже к синтаксису HQL, потому так и написал, я считал что B замаплен на A как аттрибут. Смысл запросв следующий — у нас получается 3 таблицы, одна A, другая join A и B, третья join A и C. Делаем их пересечение с использованием or, соответственно union готова.
Re[8]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 02.08.09 19:53
Оценка:
Здравствуйте, elmal, Вы писали:

D>>Сейчас под рукой даже парсера нет, но подозреваю, что ошибка в синтаксисе будет. Да и вообще не очень понял смысл запроса. У A нет информации о таблицах B и C. B, C могут связаться с A только по идентификатору из A и все. Откуда поля A.b, A.c?

E>A.b это если на sql перевести A inner join B on A.id=B.id. Я просто привык уже к синтаксису HQL, потому так и написал, я считал что B замаплен на A как аттрибут. Смысл запросв следующий — у нас получается 3 таблицы, одна A, другая join A и B, третья join A и C. Делаем их пересечение с использованием or, соответственно union готова.

Теперь понял. Lloyd предложил именно этот вариант, если не ошибаюсь:

SELECT A.*
FROM A
LEFT JOIN B ON B.a = A.a
LEFT JOIN C ON C.a = A.a
WHERE (B.a IS NOT NULL) OR (C.a IS NOT NULL)

Ты такой же предлагаешь?
Re[9]: Можно ли заменить UNION на какой-нибудь JOIN?
От: elmal  
Дата: 03.08.09 05:19
Оценка:
Здравствуйте, Donz, Вы писали:

D>Ты такой же предлагаешь?

Уже 2 раза писал, на этот раз попробую на чем-нидь похожим на SQL .
select A.* from A, A as AB join B on AB.id=B.id, A as AC join C on AC.id=C.id where A.id=AB.id or C.id=AC.id.

Алиасы забыл уже где и как ставятся, не уверен можно ли так, просто идею говорю.
Re: Можно ли заменить UNION на какой-нибудь JOIN?
От: MasterZiv СССР  
Дата: 03.08.09 06:10
Оценка: 4 (1)
Donz пишет:

> То есть, простейшее решение выглядит так:

> select A.* from A inner join B on B.a = A.a
> union
> select A.* from A inner join C on C.a = A.a
>
> Но мне надо, чтобы селект был только один,

Это и есть один селект. UNION -- это часть одного
оператора SELECT.

причем таблицы в запрос могут
> добавляться только через join'ы.
> Эти ограничения накладывает Hibernate Criteria API.

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

Ты точно так же можешь через Hib просто сделать 2-3 последовательных
запроса в одной транзакции, будет ровно то же самое.
(проблема только с дубликатами будет, но её можно
самому решить).

Так что проблема надуманная. Короче,
1) тебе это не нужно
2) формально заменить как-то UNION-ы на JOIN-ы невозможно.
Это разные операции.
Posted via RSDN NNTP Server 2.1 beta
Re: Можно ли заменить UNION на какой-нибудь JOIN?
От: MasterZiv СССР  
Дата: 03.08.09 06:15
Оценка:
Donz пишет:

А, это

select A.* from A inner join B on B.a = A.a
union
select A.* from A inner join C on C.a = A.a


можно писать так


select A.*
from A
left join B on B.a = A.a
left join C on C.a = A.a

ну и

where b.a is not null or c.a is not null

ежели надо.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: MasterZiv СССР  
Дата: 03.08.09 06:18
Оценка:
Lloyd пишет:

> SELECT A.*

> FROM A
> LEFT JOIN B ON B.a = A.a
> LEFT JOIN C ON C.a = A.a
> WHERE (B.a IS NOT NULL) OR (C.a IS NOT NULL)

СКОБКИ В WHERE Н_Е Н_А_Д_О !!

(пожалуйста )
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Можно ли заменить UNION на какой-нибудь JOIN?
От: MasterZiv СССР  
Дата: 03.08.09 06:21
Оценка:
Donz пишет:

> L>>SELECT A.*

> L>>FROM A
> L>>LEFT JOIN B ON B.a = A.a
> L>>LEFT JOIN C ON C.a = A.a
> L>>WHERE (B.a IS NOT NULL) OR (C.a IS NOT NULL)

> Можно подробнее? Оптимизацию запросов в БД начал изучать заново с

> полгода назад. Пока я в этом запросе ничего криминального не вижу.

Криминального в нём то, что нет в нём критерия выборки,
и он будет обрабатывать все записи из таблицы A. Если она большая,
то будет небыстро. Запрос же с UNION потенциально может сначала
работать через таблицы B и C, которые могут быть меньше, и за счёт
этого давать большую производительность (впрочем, её часть всё
равно сожрёт сортировка для выполнения UNION).
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Lloyd Россия  
Дата: 03.08.09 06:47
Оценка: +1
Здравствуйте, MasterZiv, Вы писали:

MZ>СКОБКИ В WHERE Н_Е Н_А_Д_О !!


MZ>(пожалуйста )


Почему? С ними гораздо читабельнее и не надо помнить о приоритете операторов.
Re[5]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Lloyd Россия  
Дата: 03.08.09 06:53
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Криминального в нём то, что нет в нём критерия выборки,

MZ>и он будет обрабатывать все записи из таблицы A. Если она большая,
MZ>то будет небыстро. Запрос же с UNION потенциально может сначала
MZ>работать через таблицы B и C, которые могут быть меньше, и за счёт
MZ>этого давать большую производительность

А если:
SELECT A.*
FROM B, C
JOIN A ON (B.a = A.a) OR (C.a = A.a)
Re: Можно ли заменить UNION на какой-нибудь JOIN?
От: . Великобритания  
Дата: 03.08.09 07:10
Оценка: +1
Donz wrote:

> Эти ограничения накладывает Hibernate Criteria API.

Если ограничения не позволяют что-то сделать, то используй HQL/createQuery, а если и HQL слабоват, то используй SQL/createSQLQuery и не мучайся. Hibernate предназначен не усложнять жизнь, а упрощать.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Можно ли заменить UNION на какой-нибудь JOIN?
От: MasterZiv СССР  
Дата: 03.08.09 07:11
Оценка:
Lloyd пишет:

> SELECT A.*

> FROM B, C
> JOIN A ON (B.a = A.a) OR (C.a = A.a)
Это вообще бред какой-то. У вас нет условия JOIN-а B и C.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Можно ли заменить UNION на какой-нибудь JOIN?
От: MasterZiv СССР  
Дата: 03.08.09 07:12
Оценка: -1
Lloyd пишет:

> Почему?


Потому что задолбало.

С ними гораздо читабельнее и не надо помнить о приоритете
> операторов.

О приоритетах операций помнить всё равно надо.
А скобки МЕШАЮТ читать.
Posted via RSDN NNTP Server 2.1 beta
Re[7]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Lloyd Россия  
Дата: 03.08.09 07:13
Оценка: +1
Здравствуйте, MasterZiv, Вы писали:

>> SELECT A.*

>> FROM B, C
>> JOIN A ON (B.a = A.a) OR (C.a = A.a)
MZ>Это вообще бред какой-то.

Где именно?

MZ>У вас нет условия JOIN-а B и C.


А B и C и не должны JOIN-иться по условию задачи.
Re[5]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Lloyd Россия  
Дата: 03.08.09 07:15
Оценка:
Здравствуйте, MasterZiv, Вы писали:

>> Почему?


MZ>Потому что задолбало.


И что?

MZ>С ними гораздо читабельнее и не надо помнить о приоритете

>> операторов.

MZ>О приоритетах операций помнить всё равно надо.


В приведенном примере не надо.

MZ>А скобки МЕШАЮТ читать.


Если только тебе. Мне лично они только помогают.
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 03.08.09 10:53
Оценка:
Здравствуйте, MasterZiv, Вы писали:

>> То есть, простейшее решение выглядит так:

>> select A.* from A inner join B on B.a = A.a
>> union
>> select A.* from A inner join C on C.a = A.a
>>
>> Но мне надо, чтобы селект был только один,

>>Я сначала составляю

>> Criteria, который является обвязкой запроса, потом отдаю его, и
>> запросивший этот Criteria может добавить еще условия по своему выбору.

MZ>Ты точно так же можешь через Hib просто сделать 2-3 последовательных

MZ>запроса в одной транзакции, будет ровно то же самое.
MZ>(проблема только с дубликатами будет, но её можно
MZ>самому решить).

Нет, не будет, так как за пределы метода, составляющего критерий, отдается не результат запроса, а объект Criteria, к которому еще будут присоединятся условия выборки. Именно поэтому мне нужен один запрос не через юнион.

MZ>Так что проблема надуманная. Короче,

MZ>1) тебе это не нужно
MZ>2) формально заменить как-то UNION-ы на JOIN-ы невозможно.
MZ>Это разные операции.

1)Это гипноз?
2)Да вроде почти получилось.

P.S. не надо так агрессивно, тут все хорошие
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 03.08.09 10:55
Оценка:
Здравствуйте, ., Вы писали:

>> Эти ограничения накладывает Hibernate Criteria API.

.>Если ограничения не позволяют что-то сделать, то используй HQL/createQuery, а если и HQL слабоват, то используй SQL/createSQLQuery и не мучайся. Hibernate предназначен не усложнять жизнь, а упрощать.

Нет, смысл в том, что у меня условия выборки будут динамически присоединяться к обсуждаемому запросу. То есть, из метода я наружу отдаю Criteria, на который можно будет наложить дополнительные ограничения.
Собственно, сила Criteria API именно в этом.
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 03.08.09 10:57
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>А, это

MZ>select A.* from A inner join B on B.a = A.a
MZ>union
MZ>select A.* from A inner join C on C.a = A.a
MZ>можно писать так
MZ>select A.*
MZ>from A
MZ>left join B on B.a = A.a
MZ>left join C on C.a = A.a
MZ>ну и
MZ>where b.a is not null or c.a is not null
MZ>ежели надо.

Угу, это как раз уже и предложили.
Re[3]: Можно ли заменить UNION на какой-нибудь JOIN?
От: MasterZiv СССР  
Дата: 03.08.09 11:10
Оценка:
Donz пишет:

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

> отдается не результат запроса, а объект Criteria, к которому еще будут
> присоединятся условия выборки. Именно поэтому мне нужен один запрос не
> через юнион.

Ты занимаешься какой-то ерундой. Ну, отдавай не Criteria, а массив Criteria.
Или отдавай что-то другое. Какая разница-то ?

> 1)Это гипноз?

> 2)Да вроде почти получилось.

Это в частном конкретном случае получилось.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Можно ли заменить UNION на какой-нибудь JOIN?
От: elmal  
Дата: 03.08.09 11:46
Оценка:
Здравствуйте, Donz, Вы писали:

D>Нет, смысл в том, что у меня условия выборки будут динамически присоединяться к обсуждаемому запросу. То есть, из метода я наружу отдаю Criteria, на который можно будет наложить дополнительные ограничения.

D>Собственно, сила Criteria API именно в этом.
Хм, у тебя задача похоже один в один как у меня была . Я например HQL динамически генерил, никакое CriteriA API не использовал. А наружу отдавал класс, на основании информации которого можно однозначно построить HQL запрос (там информация о критериях поиска, о сущностях, кто на что мапится + информация о зависимостях, ну и параметры и значения естественно). Получилось достаточно удачно, удалось выдержать впоследствии такие требования, как интеграция с внешними сервисами (то есть сначала ищем во внешних сервисах, зетем то, что они вернут, используем как параметры запроса).
Re[4]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 03.08.09 21:48
Оценка:
Здравствуйте, MasterZiv, Вы писали:

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

>> отдается не результат запроса, а объект Criteria, к которому еще будут
>> присоединятся условия выборки. Именно поэтому мне нужен один запрос не
>> через юнион.

MZ>Ты занимаешься какой-то ерундой. Ну, отдавай не Criteria, а массив Criteria.

MZ>Или отдавай что-то другое. Какая разница-то ?

Ага, например, можно отдавать число 42

Но за наводку спасибо. В конечном счете посмотрев на получившийся запрос, понял, что так класть на производительсность нельзя. Так что сделал полуобертку над хибернейтовским Criteria API, при помощи которой конечный пользователь моего пакета не будет подозревать о массиве Criteria.
Re[5]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 03.08.09 21:50
Оценка: 1 (1)
Здравствуйте, elmal, Вы писали:

E>>У меня тогда этих left join было штук 6, и каждый еще соединялся еще с несколькоми таблицами (ох хотелось тогда высказать все, что я думаю о структуре базы, еле сдержался ). С in заработало быстрее, причем раз в 100 — скорость замерял.

E>Хотя, справедливости ради, запрос у меня был несколько посложнее, там у меня была задача похожая на твою, но там связи были по простым аттрибутам, которые с таблицей B были связана еще через 5 таблиц . Они не были даже внешними ключами и на них даже индексов не висело, потому и такой результат. Потом индексы добавили, я попросил того, кто занимается оптимизацией предыдущий запрос проверить, вроде один черт left join медленнее чем вложенные селекты с in оказалось.

У меня наоборот, через джойны запрос выполнялся на порядок быстрее.
Re: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 03.08.09 21:52
Оценка:
Здравствуйте, Donz, Вы писали:

Всем спасибо.
В конечном счете из-за жесткого проседания производительности сделал через два разных Criteria, но со своей оберткой на хибернейтовским API. Таким образом, и запросы довольно шустро выполянются, и изначальное желание скрыть обязательные условия от пользователя моих классов удовлетворено.
Re[2]: Можно ли заменить UNION на какой-нибудь JOIN?
От: . Великобритания  
Дата: 03.08.09 23:05
Оценка:
. wrote:

>> Эти ограничения накладывает Hibernate Criteria API.

> Если ограничения не позволяют что-то сделать, то используй
> HQL/createQuery, а если и HQL слабоват, то используй SQL/createSQLQuery
> и не мучайся. Hibernate предназначен не усложнять жизнь, а упрощать.
Просто этот Criteria — не всемогущ, полагаю, что ты упрёшься в рамки возможностей (или уже упёрся) и придётся всё переделывать.
Так что, по-моему, это не самая лучшая идея отдавать Criteria куда-то наружу. Сделай специальный bean-объект для описания данных запроса и по нему генери что удобнее/производительнее — criteria/hql/sql.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: Можно ли заменить UNION на какой-нибудь JOIN?
От: Donz Россия http://donz-ru.livejournal.com
Дата: 04.08.09 15:22
Оценка:
Здравствуйте, ., Вы писали:

.>Просто этот Criteria — не всемогущ, полагаю, что ты упрёшься в рамки возможностей (или уже упёрся) и придётся всё переделывать.

.>Так что, по-моему, это не самая лучшая идея отдавать Criteria куда-то наружу. Сделай специальный bean-объект для описания данных запроса и по нему генери что удобнее/производительнее — criteria/hql/sql.

Пока еще не уперся. У меня уже есть обертка. Пока она почти напрямую работает с Criteria. Как не будет хватать — расширю функционал.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.