powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Сложный select
11 сообщений из 11, страница 1 из 1
Сложный select
    #32027596
Фотография snake
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть 2 таблицы со связью 1:N.
Задача выбрать одним запросом все поля из 1 и 2 таблицы, взяв из 2-ой одну запись с
максимальным/минимальным/средним(утрирую) номером.
Пример:
tab1
id name
1 ddd
2 dff
3 ggh
tab2
id_tab1 id data
1 1 '2002.1.1'
1 2 '2002.1.3'
2 10 '2002.3.1'
2 11 '2002.3.2'
Результат:
tab1.id tab1.name tab2.id_tab1 tab2.id tab2.data
1 ddd 1 1 '2002.1.1'
2 dff 2 10 '2002.3.1'
3 ggh null null null
...
Рейтинг: 0 / 0
Сложный select
    #32027608
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
select t1.*, t2.*
from
(select t1.*, (select top 1 id from table2 t2 where t2.id_tab1 = t1.id order by t2.date desc) AS t2_id
from table1 t1
) AS t1
left outer join table2 t2 on t2.id = t1.t2_id
...
Рейтинг: 0 / 0
Сложный select
    #32027680
Michael+Hopgarden
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 Glory, All

Хочу услышать критику другого варианта, при условии, что значения tab2.data уникальны в пределах tab2.id_tab1

set nocount on
create table #tab1 (id int, name varchar(3))
insert #tab1 (id, name) select 1, 'ddd'
insert #tab1 (id, name) select 2, 'dff'
insert #tab1 (id, name) select 3, 'ggh'
create table #tab2 (id_tab1 int, id int, data int)
insert #tab2 (id_tab1, id, data) select 1, 1, 20020101
insert #tab2 (id_tab1, id, data) select 1, 2, 20020103
insert #tab2 (id_tab1, id, data) select 2, 10, 20020301
insert #tab2 (id_tab1, id, data) select 2, 11, 20020302

select t1.id, t1.name, t2.id_tab1, t2.id, t2.data
from
(select id_tab1, min(data) as min_data from #tab2 group by id_tab1) as t
inner join
#tab2 as t2 on t2.id_tab1 = t.id_tab1 and t2.data = t.min_data
right outer join
#tab1 as t1 on t1.id = t2.id_tab1

/* Вариант Glory
select t1.id, t1.name, t2.id_tab1, t2.id, t2.data
from
(select t1.*, (select top 1 id from #tab2 t2 where t2.id_tab1 = t1.id order by t2.data asc) AS t2_id
from #tab1 t1
) AS t1
left outer join #tab2 t2 on t2.id = t1.t2_id
*/
drop table #tab1
drop table #tab2
set nocount off

P.S. Понятнее, проще и удобнее в прочтении и написании критикой не признается
...
Рейтинг: 0 / 0
Сложный select
    #32027691
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IMHO
- для уникальных значений tab2.data в пределах tab2.id_tab1 ваш запрос лучше
- а вот для неуникальных, запрос не выполнит ваше же условие "взяв из 2-ой одну запись"

Так что - каждому свое.


ЗЫ
В начальном сообщении вы не сказали ничего насчет уникальности/неуникальности, поэтому я и предложил более общий пример.
...
Рейтинг: 0 / 0
Сложный select
    #32027694
Фотография snake
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ребят, а если id составной(а не одним полем)?
...
Рейтинг: 0 / 0
Сложный select
    #32027697
Michael+Hopgarden
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 Snake

Если уникальность присутствует, подойдет и мой вариант. Добавьте ключ в qroup by и условия соединения.
Если нет, то можно, например, через временную
таблицу с identity_id, заполненную в нужном вам порядке. А из нее уже по min|max|(identity_id). Критика принимается.
...
Рейтинг: 0 / 0
Сложный select
    #32027701
Фотография snake
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересно, а часто ли в БД (по "уму" спроектированных)
приходится переходить от связи 1:N к 1:1 или мне пересмотреть
структуру?
...
Рейтинг: 0 / 0
Сложный select
    #32027729
Michael+Hopgarden
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 Glory

И, все таки, сомнения остаются. Может быть прокомментируете.

Стоит добавить primary key.
alter table #tab1 add constraint pk1 primary key(id)
alter table #tab2 add constraint pk2 primary key(id)
и Ваш запрос становится шустрее.

Не спасает даже индексирование.
create index idx on #tab2(id_tab1)
create index idx2 on #tab2(data)
Надо будет посмотреть на больших объемах.
...
Рейтинг: 0 / 0
Сложный select
    #32027735
Фотография snake
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Glory
Не раз наверное слышали спасибо в свой адрес?
Очередное ...
2 Michael+Hopgarden
Решений действительно несколько. Из всех нами придуманных решение Glory эффективнее
(проверено и набольших обьемах) да просто достатоно взглянуть на план.
...
Рейтинг: 0 / 0
Сложный select
    #32027737
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Michael+Hopgarden
Да, действительно при clustered primary key из плана "моего" запроса пропадает один Hash Join. А во втором запросе всегда остается шаг Table Spool/Lazy Spool, что мне лично не нравится. Это первое.
Второе, из того же плана выполнения видно каждый шаг "моего" запроса дает меньше(или не больше) записей на выходе, чем у запроса Snake.

Хотя странно, что при совместном выполнении, QA показывает незначительное преимущество запроса от Snake. 48% vs 52%. Без primary key перекос еще больше 41 vs 59

2Snake
Если не секрет, на каких конкретно больших объемах вы проверяли запросы ?

И за спасибо - спасибо
. Доброе слово оно, как говорится, и кошке приятно.
...
Рейтинг: 0 / 0
Сложный select
    #32027761
Фотография snake
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Glory
Проверял на 2 таблицах:
1 - 40 полей (в основном char не больше 10 байт)
2 - 83 поля (6 - полей text, остальные char не больше 10 байт и несколько целых)
В обоих таблицах первичный ключ по полю int (IDENTITY) кластерный, но
связка проходит по нескольки полям, по которым построен уникальный индекс.
В левой таблице 107955 записей.
И соответственно результат за 1 мин. 28 сек. (123 поля, 107955 записей)
PS
win2k as sp1, sql2k sp2,2-P3 - 700Mh,RAID5,1Gb RAM
PPS
Сообственно вот сам запрос:
select t1.*, t2.*
from
(select t1.*, (select top 1 nidn from reestr t2 where
t2.filial = t1.filial and
t2.kniga = t1.kniga and
t2.god_kn = t1.god_kn and
t2.nomerkn = t1.nomerkn and
t2.nomerreg = t1.nomerreg
order by t2.nidn asc) AS t2_nidn
from status t1
) AS t1
left outer join reestr t2 on
t2.filial = t1.filial and
t2.kniga = t1.kniga and
t2.god_kn = t1.god_kn and
t2.nomerkn = t1.nomerkn and
t2.nomerreg= t1.nomerreg and
t2.nidn = t1.t2_nidn
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Сложный select
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]