В SQL не хватает подвариантов join?
От: _ilya_  
Дата: 08.02.17 18:38
Оценка:
Достаточно типичные и простые задачи выливаются в нагромождение запросов и при больших объемах они еще и могут неадекватно тормозить.
Пример — две таблицы, в первой допустим продажа клиенту, с полями дата, клиент,.... В связанной детализация продажи — товар, количество, цена.
Нужен отчет типа клиент и самая дорогая позиция в чеке. И вот элементарно просто такой простой случай не реализуем.

Пример:
T1

ID КлиентID Дата
1 1 01.01.17
2 2 01.01.17


T2
ID T1ID ТоварID Цена
1 1 1 100
2
1 2 200
3
2 3 110
4
2 4 220


В результате допустим требуется так:

ТоварID КлиентID Цена
4 2 220
2
1 200

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

P.S. Ну а нужно что то типа left join top 1, т.е. выбрать не все, а присоединить что-то одно с учетом сортировки например.
Отредактировано 08.02.2017 18:40 _ilya_ . Предыдущая версия . Еще …
Отредактировано 08.02.2017 18:39 _ilya_ . Предыдущая версия .
Re: В SQL не хватает подвариантов join?
От: vmpire Россия  
Дата: 08.02.17 19:15
Оценка: +2
Здравствуйте, _ilya_, Вы писали:

__>Достаточно типичные и простые задачи выливаются в нагромождение запросов и при больших объемах они еще и могут неадекватно тормозить.

__>Пример — две таблицы, в первой допустим продажа клиенту, с полями дата, клиент,.... В связанной детализация продажи — товар, количество, цена.
__>Нужен отчет типа клиент и самая дорогая позиция в чеке. И вот элементарно просто такой простой случай не реализуем.

...

__>P.S. Ну а нужно что то типа left join top 1, т.е. выбрать не все, а присоединить что-то одно с учетом сортировки например.

RANK() или ROW_NUMBER() поверх обычного джойна с фильтром по результату ranking function
Re: В SQL не хватает подвариантов join?
От: _ABC_  
Дата: 08.02.17 19:51
Оценка:
Здравствуйте, _ilya_, Вы писали:

__>Достаточно типичные и простые задачи выливаются в нагромождение запросов и при больших объемах они еще и могут неадекватно тормозить.

__>Пример — две таблицы, в первой допустим продажа клиенту, с полями дата, клиент,.... В связанной детализация продажи — товар, количество, цена.
__>Нужен отчет типа клиент и самая дорогая позиция в чеке. И вот элементарно просто такой простой случай не реализуем.

Что-то типа этого нужно, что ли?
;with p as (    
    select itemId, clientID, price, row_number() over (partition by clientID order by price desc) rn
    from t1
    join t2 on t1.id = t2.t1id
)
select itemID, clientID, price
from p
where rn = 1


И что в этом нереализуемого и чем это хуже придуманного тобой (пример, кстати, напиши полностью)?
Re: В SQL не хватает подвариантов join?
От: night beast СССР  
Дата: 08.02.17 19:52
Оценка:
Здравствуйте, _ilya_, Вы писали:

__>Достаточно типичные и простые задачи выливаются в нагромождение запросов и при больших объемах они еще и могут неадекватно тормозить.

__>Пример — две таблицы, в первой допустим продажа клиенту, с полями дата, клиент,.... В связанной детализация продажи — товар, количество, цена.
__>Нужен отчет типа клиент и самая дорогая позиция в чеке. И вот элементарно просто такой простой случай не реализуем.

__>С вложенными запросами могут быть тормоза в сложных случаях. С созданием временной таблицы и затем вторым запросом выборка из нее время более адекватно, но красивости нет. Неужели SQL настолько ничтожен, что элементарное так ужасно получить?


__>P.S. Ну а нужно что то типа left join top 1, т.е. выбрать не все, а присоединить что-то одно с учетом сортировки например.


в постгресе distinct on есть
Re: В SQL не хватает подвариантов join?
От: Olaf Россия  
Дата: 09.02.17 07:43
Оценка:
Здравствуйте, _ilya_, Вы писали:

__>...


__>С вложенными запросами могут быть тормоза в сложных случаях. С созданием временной таблицы и затем вторым запросом выборка из нее время более адекватно, но красивости нет. Неужели SQL настолько ничтожен, что элементарное так ужасно получить?


__>P.S. Ну а нужно что то типа left join top 1, т.е. выбрать не все, а присоединить что-то одно с учетом сортировки например.


Аналогичная тема обсуждалась здесь Объединить две таблицы, но из второй таблицы использовать только одну запись
Re: В SQL не хватает подвариантов join?
От: MasterZiv СССР  
Дата: 13.02.17 12:06
Оценка:
Здравствуйте, _ilya_, Вы писали:

__>Достаточно типичные и простые задачи выливаются в нагромождение запросов и при больших объемах они еще и могут неадекватно тормозить.


При больших объёмах всё может тормозить...

__>Пример — две таблицы, в первой допустим продажа клиенту, с полями дата, клиент,.... В связанной детализация продажи — товар, количество, цена.

__>Нужен отчет типа клиент и самая дорогая позиция в чеке. И вот элементарно просто такой простой случай не реализуем.

JOIN+GROUP BY


__>С вложенными запросами могут быть тормоза в сложных случаях.


C чего ты взял ?

С созданием временной таблицы и затем вторым запросом выборка из нее время более адекватно, но красивости нет. Неужели SQL настолько ничтожен, что элементарное так ужасно получить?

Просто нужно им владеть, ты, видимо, не умеешь.
Re[2]: В SQL не хватает подвариантов join?
От: _ilya_  
Дата: 17.02.17 17:47
Оценка: -2 :)
Здравствуйте, MasterZiv, Вы писали:

__>>С вложенными запросами могут быть тормоза в сложных случаях.


MZ>C чего ты взял ?


Вообщем все переписано на left join и временные таблицы. Скорость — даже не ожидал что так быстро будет. Код конечно многостраничный, чтобы притянуть вот то поле из вложенной вот в ту вложенную и только первое (одно значение), а если связей нет то NULL. Весь запрос разрастается на десяток страниц и это ад, если не осведомленному в таком мракобесии разбираться. Тривиальная штука выливается в трудно осмысленный код когда его еще и много.

Вложенный запрос вида select * from #T99 as fignia where fignia.link in (select link from #T98) неадекватно убивает сервер даже на сотни тысячах записей. На дохлом тест сервере 20 минут, на рабочем и вроде как крутом 1 час 40 в не рабочее время! Заодно порешали аппаратную проблему с рабочим сервером. Left join (top 1) (sort by) — типа присоединить один отсортировав выборку по таким то полям — крайне не хватает для лаконичности, наверно и на скорость бы повлияло особенно если нужно присоединить одно первое попавшееся поле.
Re[3]: В SQL не хватает подвариантов join?
От: _ABC_  
Дата: 21.02.17 06:30
Оценка: +2
Здравствуйте, _ilya_, Вы писали:

__>Вложенный запрос вида select * from #T99 as fignia where fignia.link in (select link from #T98) неадекватно убивает сервер даже на сотни тысячах записей. На дохлом тест сервере 20 минут, на рабочем и вроде как крутом 1 час 40 в не рабочее время! Заодно порешали аппаратную проблему с рабочим сервером. Left join (top 1) (sort by) — типа присоединить один отсортировав выборку по таким то полям — крайне не хватает для лаконичности, наверно и на скорость бы повлияло особенно если нужно присоединить одно первое попавшееся поле.


Сдается мне, что если вы возьмете в штат хоть одного человека, умеющего в РСУДБ, это всё превратится в изящный код, который легко
читать и поддерживать. Ну и время выполнения уменьшится, разумеется.
Re[3]: В SQL не хватает подвариантов join?
От: Olaf Россия  
Дата: 22.02.17 03:20
Оценка:
Здравствуйте, _ilya_, Вы писали:

__>... Left join (top 1) (sort by) — типа присоединить один отсортировав выборку по таким то полям — крайне не хватает для лаконичности, наверно и на скорость бы повлияло особенно если нужно присоединить одно первое попавшееся поле.


Вы до сих пор не назвали ни СУБД ни версию, чтобы правильно ответить на ваш вопрос. А в SQL Server 2005+, например, для "лаконичности" есть конструкция OUTER APPLY, которая позволяет реализовать вашу задачу:
select *
from dbo.T1 t1
outer apply
(
    select top 1 *
    from dbo.T2 t2
    where t1.T1Id = t2.T1Id
    order by t2.Name
) a
Re[4]: В SQL не хватает подвариантов join?
От: _ilya_  
Дата: 22.02.17 17:39
Оценка: -1
Здравствуйте, _ABC_, Вы писали:

_AB>Сдается мне, что если вы возьмете в штат хоть одного человека, умеющего в РСУДБ, это всё превратится в изящный код, который легко

_AB>читать и поддерживать. Ну и время выполнения уменьшится, разумеется.

Знающих в MS SQL таких пока 0 и таких вакансий 10 лет не открывалось, есть только спецы по Oracle но они не помошники. Без всякого одного, теперь это выполняется за 2 минуты — в результате 150тыс записей с тучей left join и временных таблиц. Видимо иначе никак не будет адекватно быстро работать. На багах учатся... Код конечно разросся и мало читабелен, но стал крайне шустро работать. Из базы в 40GB выбрать много связанного с "нерешенным" для sql left join first 1 выглядит более чем достаточная скорость. Изящности точно не будет — временные таблицы, выборка из них первого во временную, далее включение в основной запрос.
Отредактировано 22.02.2017 17:40 _ilya_ . Предыдущая версия .
Re[4]: В SQL не хватает подвариантов join?
От: _ilya_  
Дата: 22.02.17 17:48
Оценка:
Здравствуйте, Olaf, Вы писали:


O>Вы до сих пор не назвали ни СУБД ни версию, чтобы правильно ответить на ваш вопрос. А в SQL Server 2005+, например, [/sql]

SQl — MS 2012, но промежуточный движок и Oracle и PostgreSql поддерживает, так что запросы ограничены скорее крайне древним диалектом SQL. Если не все SQL такие конструкции переваривают, то и нет поддержки даже если при таком уникальном сервере такая конструкция работоспособна.

Вообще без временных таблиц возможно ли присоединить к выборке из связанной таблицы не все, а только 1 элемент с такой то сортировкой, если связь многие ко многим?
Такое ощущение что изначально такое не заложено в язык и только временные таблицы (или подзапросы, которые жутко тормознее) спасают.
Отредактировано 22.02.2017 18:24 _ilya_ . Предыдущая версия . Еще …
Отредактировано 22.02.2017 17:57 _ilya_ . Предыдущая версия .
Отредактировано 22.02.2017 17:57 _ilya_ . Предыдущая версия .
Отредактировано 22.02.2017 17:56 _ilya_ . Предыдущая версия .
Отредактировано 22.02.2017 17:49 _ilya_ . Предыдущая версия .
Отредактировано 22.02.2017 17:49 _ilya_ . Предыдущая версия .
Re[5]: В SQL не хватает подвариантов join?
От: _ABC_  
Дата: 22.02.17 17:57
Оценка:
Здравствуйте, _ilya_, Вы писали:

__>Знающих в MS SQL таких пока 0 и таких вакансий 10 лет не открывалось, есть только спецы по Oracle но они не помошники. Без всякого одного, теперь это выполняется за 2 минуты — в результате 150тыс записей с тучей left join и временных таблиц. Видимо иначе никак не будет адекватно быстро работать.

Вот это "видимо" крайне сомнительно. Крайне. Я это к тому, что не надо обвинять инструмент, который ты не знаешь и делать выводы по нему.
Re[6]: В SQL не хватает подвариантов join?
От: _ilya_  
Дата: 22.02.17 18:04
Оценка:
Здравствуйте, _ABC_, Вы писали:

_AB>Вот это "видимо" крайне сомнительно. Крайне. Я это к тому, что не надо обвинять инструмент, который ты не знаешь и делать выводы по нему.


Я просто не вижу простого решения присоединить таблицу и если есть соответствие, то выбрать только одно значение а не все (с учетом моей заданной сортировки). Это в классическом SQL, разные подварианты SQL серверов видимо имеют такие возможности, но нифига не обобщен стандарт на такое.
Чтобы на всех платформах было просто и лаконично — выбрать например все продажи и максимальную цену из чека... Чего проще, то — все из первой и при наличии связи например max(price) из связанной второй таблицы?
Вся такая не лаконичность и разность платформ, выливается в то, что например спецы по Oracle которым много денег платят, не отвечают за MS SQL, а если в MS SQL такой запрос писать без временных таблиц, а на сильно тормозящих вложенных подзапросах, то все выливается в мегафейл. Тут и к оптимизатору SQL сервера тоже вопросы... написано 2 запроса — через left join и через вложенный запрос. Разница по скорости — порядок, а результат и замысел естественно один ибо запрос одинаков по сути и возвращает всегда одинаковый результат.
Отредактировано 22.02.2017 18:19 _ilya_ . Предыдущая версия . Еще …
Отредактировано 22.02.2017 18:17 _ilya_ . Предыдущая версия .
Отредактировано 22.02.2017 18:11 _ilya_ . Предыдущая версия .
Отредактировано 22.02.2017 18:05 _ilya_ . Предыдущая версия .
Отредактировано 22.02.2017 18:04 _ilya_ . Предыдущая версия .
Re[7]: В SQL не хватает подвариантов join?
От: _ABC_  
Дата: 22.02.17 18:40
Оценка:
Здравствуйте, _ilya_, Вы писали:

__>Вся такая не лаконичность и разность платформ, выливается в то, что например спецы по Oracle которым много денег платят, не отвечают за MS SQL

А специалисты по Java не отвечают за .Net...

__>а если в MS SQL такой запрос писать без временных таблиц, а на сильно тормозящих вложенных подзапросах, то все выливается в мегафейл.

А если использовать современный синтаксис T-SQL, то временные таблицы по-прежнему нужны?
Если нет, то какие претензии к СУБД?

__>Тут и к оптимизатору SQL сервера тоже вопросы... написано 2 запроса — через left join и через вложенный запрос. Разница по скорости — порядок, а результат и замысел

Почему left join противопоставляется вложенному запросу? Вложенный запрос может быть присоединен через left join.
Покажи, что ты имеешь в виду, пожалуйста. Тестовые данные для твоего примера.

create table t1 (id int identity primary key, clientID int, _date date)
create table t2 (id int identity primary key, t1ID int, itemID int, price money)
alter table t2 add constraint fk_t1ID foreign key (t1ID) references t1(id)


insert into t1 (clientID, _date)
select 1, '2017-01-01' union all
select 2, '2017-01-01'

insert into t2(t1ID, itemID, price)
select 1, 1, 100 union all
select 1, 2, 200 union all
select 2, 3, 110 union all
select 2, 4, 220
Re[8]: В SQL не хватает подвариантов join?
От: _ilya_  
Дата: 22.02.17 19:24
Оценка:
Здравствуйте, _ABC_, Вы писали:

__>>Вся такая не лаконичность и разность платформ, выливается в то, что например спецы по Oracle которым много денег платят, не отвечают за MS SQL

_AB>А специалисты по Java не отвечают за .Net...


__>>Тут и к оптимизатору SQL сервера тоже вопросы... написано 2 запроса — через left join и через вложенный запрос. Разница по скорости — порядок, а результат и замысел

_AB>Почему left join противопоставляется вложенному запросу? Вложенный запрос может быть присоединен через left join.
_AB>Покажи, что ты имеешь в виду, пожалуйста. Тестовые данные для твоего примера.
_AB>[/sql]

Диалекты SQl не должны так откровенно разделять специалистов... Думаю что если загнется один из подвидов, то что будут делать те, кто не в курсе остальных разновидностей? Может им стоит знать немного и про конкурирующие диалекты? По факту они не знают и не умеют ничего — тот же MS SQL DTS крайне полезное открытие, для тех кто знает Oracle если проблемы с типами при переносе данных, когда тупо из MS не могут забрать данные.

По скорости left join против вложенного подзапроса, select * from xren as t1 where t1.id in (select id from t2) крайне медленно работает. Видимо подзапросы вовсе не оптимизируются с привязкой к верхнеуровнему запросу и когда много вложений там ад с таким. Собственно видимо устаревшая конструкция классического sql и временные таблицы полностью заменили эту классику как подзапросы. Но совместимость должна обеспечиваться, ибо древний язык.
Отредактировано 22.02.2017 19:25 _ilya_ . Предыдущая версия .
Re[9]: В SQL не хватает подвариантов join?
От: _ABC_  
Дата: 22.02.17 19:52
Оценка:
Здравствуйте, _ilya_, Вы писали:

__>Диалекты SQl не должны так откровенно разделять специалистов...

Кому не должны?
Почему разные языки программирования имеют право откровенно разделять специалистов, а СУБД не могут?

__>Думаю что если загнется один из подвидов, то что будут делать те, кто не в курсе остальных разновидностей? Может им стоит знать немного и про конкурирующие диалекты?

Для общего развития — разумеется стоит. Для работы — особо не нужно.

__>По факту они не знают и не умеют ничего — тот же MS SQL DTS крайне полезное открытие

SSIS (бывший DTS) не относится к диалекту языка (Transact-SQL) вообще никак.

__>По скорости left join против вложенного подзапроса, select * from xren as t1 where t1.id in (select id from t2) крайне медленно работает.

Начнем с того, что
select * 
from xren as t1 
where t1.id in (select id from t2)

Это вовсе не то же самое, что
select * 
from xren as t1 
left join t2 on t1.id = t2.id
where t1.id in (select id from t2)

И даже если left join заменить на inner join, всё равно это разные по смыслу запросы, которые могут
давать один и тот же результат лишь в частном случае. Поэтому совершенно логично, если в общем случае
у этих двух запросов будут разные планы с разной производительностью.

__>Видимо подзапросы вовсе не оптимизируются с привязкой к верхнеуровнему запросу и когда много вложений там ад с таким.

Оптимизируются. Но SQL — интерпретируемый язык и оптимизатору нужно выбирать между скоростью подбора плана и его оптимальностью.
Я не думаю, что ты бы хотел, чтобы сервер каждый раз выбирал оптимальный план по несколько секунд.
Поэтому для сложных запросов часты ситуации, когда план выбран с причиной "good enough plan found" или даже "timeout".

Исправить ситуацию можно разными способами, начиная от тривиального упрощения запросов, до подсказок оптимизатору на
уровне check constraint и статистик, или прямых указаний хинтов (что, в свою очередь, может привести к проблемам в будущем).

__>Но совместимость должна обеспечиваться, ибо древний язык.

А все программисты должны писать на C.
Re[5]: В SQL не хватает подвариантов join?
От: Olaf Россия  
Дата: 27.02.17 07:37
Оценка: +1
Здравствуйте, _ilya_, Вы писали:

__>SQl — MS 2012, но промежуточный движок и Oracle и PostgreSql поддерживает, так что запросы ограничены скорее крайне древним диалектом SQL. Если не все SQL такие конструкции переваривают, то и нет поддержки даже если при таком уникальном сервере такая конструкция работоспособна.


__>Вообще без временных таблиц возможно ли присоединить к выборке из связанной таблицы не все, а только 1 элемент с такой то сортировкой, если связь многие ко многим?

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

Так если нужно поддерживать реализацию для нескольких СУБД, значит нужно стремиться к использованию стандарта ANSI SQL. В частности в SQL:2003 были введены оконные функции в лице row_number. Я очень бегло посмотрел, но PostgreSQL и Oracle их по-моему поддерживают, зависит конечно от версии. Собственно самым первым ответом в этом топике, было предложено использовать данный подход, а именно:
select *
from dbo.T1 t1
left join
(
    select *, row_number() over(partition by t2.T1Id order by t2.Name) as n
    from dbo.T2 t2
) t2 on t1.T1Id = t2.T1Id and t2.n = 1
Re: В SQL не хватает подвариантов join?
От: Sammo Россия  
Дата: 27.02.17 09:48
Оценка: +1
__>Достаточно типичные и простые задачи выливаются в нагромождение запросов и при больших объемах они еще и могут неадекватно тормозить.
__>Пример — две таблицы, в первой допустим продажа клиенту, с полями дата, клиент,.... В связанной детализация продажи — товар, количество, цена.

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


Стесняюсь спросить, а в продажах индекс по ID продажи какой-нибудь есть?
А то видел как-то жалобы на производительность в похожем случае, и оказалась такая оказия.
Re[5]: В SQL не хватает подвариантов join?
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.03.17 04:24
Оценка:
Здравствуйте, _ilya_, Вы писали:
__>Знающих в MS SQL таких пока 0 и таких вакансий 10 лет не открывалось, есть только спецы по Oracle но они не помошники. Без всякого одного, теперь это выполняется за 2 минуты — в результате 150тыс записей с тучей left join и временных таблиц.
Я уже лет 20 не видел ситуаций, где временные таблицы были бы как-то оправданы.
Вам остро не хватает человека, способного читать и анализировать execution plan.
Без него ваши попытки обречены — через пару лет ваш код с с тучей left join и временных таблиц станет беспричинно тормозить.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: В SQL не хватает подвариантов join?
От: Sammo Россия  
Дата: 01.03.17 05:41
Оценка:
__>Вложенный запрос вида select * from #T99 as fignia where fignia.link in (select link from #T98) неадекватно убивает сервер даже на сотни тысячах записей.
У меня опыт весьма специфический. Но по нему у меня получалось, что
1. При большом результате лучше использовать exists вместо in
2. Вариант соединения вместо exists работает примерно также.
Поэтому: индексы + запрос.
При этом я несколько потерялся — сначала речь идет про join, а потом плавно переходит на in
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.