Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как сделать одним запросом? / 21 сообщений из 21, страница 1 из 1
15.02.2022, 18:14
    #40134322
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Есть такая задача (не студент, просто нашел):

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
declare @products TABLE (
[name] nvarchar(50),
[size] smallint,
[cat] nvarchar(50),
[cond] nvarchar(50),
[created] datetime not null default getdate()
);

declare @SizeRanges1  TABLE (
LimL1 smallint,
LimU1 smallint,
Description1 varchar(20)
);
declare @SizeRanges2  TABLE (
LimL2 smallint,
LimU2 smallint,
Description2 varchar(40)
);

insert into @Products(name, size, cat, cond) values(N'Product1', 20,  N'Phone1', N'OK');

insert into @Products(name, size, cat, cond) values(N'Product1', 20,  N'Phone1', N'OK');
insert into @Products(name, size, cat, cond) values(N'Product1', 20,  N'Phone1', N'OK');
insert into @Products(name, size, cat, cond) values(N'Product2', 400, N'Note2', N'OKOK' );
insert into @Products(name, size, cat, cond) values(N'Product3', 255, N'Note', N'OK');
insert into @Products(name, size, cat, cond) values(N'Product4', 385, N'Note', N'OK');
insert into @Products(name, size, cat, cond) values(N'Product5', 420, N'Note', N'SOSO');
insert into @Products(name, size, cat, cond) values(N'Product5', 420, N'Note', N'OK');
insert into @Products(name, size, cat, cond) values(N'Product7', 8800, N'No', N'OK');

insert into @SizeRanges1(limL1, LimU1, Description1) values (0, 25, N'Малый');
insert into @SizeRanges1(limL1, LimU1, Description1) values (26, 100, N'Маленький');
insert into @SizeRanges1(limL1, LimU1, Description1) values (405, 418, N'Средний');
insert into @SizeRanges1(limL1, LimU1, Description1) values (600, 700, N'Большой');
insert into @SizeRanges2(limL2, LimU2, Description2) values (200, 280, N'Элька');
insert into @SizeRanges2(limL2, LimU2, Description2) values (300, 500, N'Эмка');
insert into @SizeRanges2(limL2, LimU2, Description2) values (1000, 5000, N'Офигенный');



Надо одним запросом выбрать все записи из таблицы @products и
размеры из SizeRanges1, если нет в SizeRanges1 тогда из SizeRanges2, если и там нет, то написать 'XEZ'.

Например, так я выбрал продукты и размеры из @SizeRanges1:
select * from @Products p inner join @SizeRanges1 n on
p.Size between n.LimL1 and n.LimU1

Но вот как одним запросом такое сделать для всех?
...
Рейтинг: 0 / 0
15.02.2022, 18:33
    #40134330
godsql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Нифига не понял, что мешает использовать два раза Left join, а потом отфильтровать пустышки
Или обычный Union хоть по двум результатам, хоть запрос по результату union
...
Рейтинг: 0 / 0
15.02.2022, 18:35
    #40134332
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
godsql
Нифига не понял, что мешает использовать два раза Left join, а потом отфильтровать пустышки


Чисто по-человечески я понимаю, как делать, но в том и вопрос: как сделать всё одним запросом.
...
Рейтинг: 0 / 0
15.02.2022, 18:37
    #40134335
godsql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Это и будет "одним запросом".
Или что имеется ввиду? Одно слово "select"?
...
Рейтинг: 0 / 0
15.02.2022, 18:41
    #40134337
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
godsql
Это и будет "одним запросом".
Или что имеется ввиду? Одно слово "select"?


Нет, не одно слово селект, естественно.
...
Рейтинг: 0 / 0
15.02.2022, 18:58
    #40134339
godsql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
там все-таки пересекаются диапазоны.
Тогда ID таблицы нужно использовать
...
Рейтинг: 0 / 0
15.02.2022, 19:01
    #40134341
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
godsql
Самый простой способ
Код: sql
1.
2.
3.
4.
5.
6.
select P.*, ISNULL(S.Description1, 'XEZ') from @Products P
LEFT JOIN (
SELECT limL1, LimU1, Description1 FROM @SizeRanges1
UNION 
SELECT * FROM @SizeRanges2
) S ON P.Size between S.LimL1 and S.LimU1



name size cat cond created (Отсутствует имя столбца)
Product1 20 Phone1 OK 2022-02-15 18:56:50.033 Малый
Product1 20 Phone1 OK 2022-02-15 18:56:50.033 Малый
Product1 20 Phone1 OK 2022-02-15 18:56:50.033 Малый
Product2 400 Note2 OKOK 2022-02-15 18:56:50.033 Эмка
Product3 255 Note OK 2022-02-15 18:56:50.033 Элька
Product4 385 Note OK 2022-02-15 18:56:50.033 Эмка
Product5 420 Note SOSO 2022-02-15 18:56:50.033 Эмка
Product5 420 Note OK 2022-02-15 18:56:50.033 Эмка
Product7 8800 No OK 2022-02-15 18:56:50.033 XEZ


Я вот такое еще накрутил

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select * from @Products p inner join @SizeRanges1 n on p.Size between n.LimL1 and n.LimU1
union all
select * from @Products p inner join @SizeRanges2 n on p.Size between n.LimL2 and n.LimU2
union all
select p.*, '0' as LimL3,  '0' as LimU3, N'XEZ' as Description3  from @Products p where 
(
	not exists(select 1 from @SizeRanges2 n2 where p.Size between n2.LimL2 and n2.LimU2)
	and 
	not exists(select 1 from @SizeRanges1 n1 where p.Size between n1.LimL1 and n1.LimU1)
)
...
Рейтинг: 0 / 0
15.02.2022, 19:04
    #40134343
godsql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
не заметил пересечений.
чуть по-позже напишу
...
Рейтинг: 0 / 0
15.02.2022, 19:08
    #40134346
godsql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
я извиняюсь, а зачем все это?
м.б. я чего-то не понимаю, и вам нужен какой-то другой результат?
приложите ожидаемый выход
а так же, что ожидается при size = 410
Ролг Хупин
godsql
Самый простой способ
Код: sql
1.
2.
3.
4.
5.
6.
select P.*, ISNULL(S.Description1, 'XEZ') from @Products P
LEFT JOIN (
SELECT limL1, LimU1, Description1 FROM @SizeRanges1
UNION 
SELECT * FROM @SizeRanges2
) S ON P.Size between S.LimL1 and S.LimU1



name size cat cond created (Отсутствует имя столбца)
Product1 20 Phone1 OK 2022-02-15 18:56:50.033 Малый
Product1 20 Phone1 OK 2022-02-15 18:56:50.033 Малый
Product1 20 Phone1 OK 2022-02-15 18:56:50.033 Малый
Product2 400 Note2 OKOK 2022-02-15 18:56:50.033 Эмка
Product3 255 Note OK 2022-02-15 18:56:50.033 Элька
Product4 385 Note OK 2022-02-15 18:56:50.033 Эмка
Product5 420 Note SOSO 2022-02-15 18:56:50.033 Эмка
Product5 420 Note OK 2022-02-15 18:56:50.033 Эмка
Product7 8800 No OK 2022-02-15 18:56:50.033 XEZ


Я вот такое еще накрутил

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select * from @Products p inner join @SizeRanges1 n on p.Size between n.LimL1 and n.LimU1
union all
select * from @Products p inner join @SizeRanges2 n on p.Size between n.LimL2 and n.LimU2
union all
select p.*, '0' as LimL3,  '0' as LimU3, N'XEZ' as Description3  from @Products p where 
(
	not exists(select 1 from @SizeRanges2 n2 where p.Size between n2.LimL2 and n2.LimU2)
	and 
	not exists(select 1 from @SizeRanges1 n1 where p.Size between n1.LimL1 and n1.LimU1)
)

...
Рейтинг: 0 / 0
15.02.2022, 19:31
    #40134351
godsql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Ну, как-то так, если не думать особо :)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select P.*, ISNULL(S.Description1, 'XEZ') SIZE_DESC 
	from @Products P
OUTER APPLY 
(SELECT TOP 1 * FROM 
(
SELECT limL1, LimU1, Description1, 1 as N FROM @SizeRanges1 
UNION 
SELECT *, 2 FROM @SizeRanges2 
) T   WHERE P.Size between T.LimL1 and T.LimU1 
ORDER BY T.N
) S
...
Рейтинг: 0 / 0
15.02.2022, 19:37
    #40134353
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Ролг Хупин
как одним запросом такое сделать для всех?

Не, а где эталонный (требуемый) результат для этих данных-то?
...
Рейтинг: 0 / 0
15.02.2022, 19:44
    #40134354
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Код: sql
1.
2.
3.
4.
5.
6.
SELECT DISTINCT
       t0.*,
       COALESCE(t1.Description1, t2.Description2, 'XYZ') Description
FROM Products t0
LEFT JOIN SizeRanges1 t1 ON t0.size BETWEEN t1.LimL1 AND t1.LimU1
LEFT JOIN SizeRanges2 t2 ON t0.size BETWEEN t2.LimL2 AND t2.LimU2;


https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=ddf757a30441a25e5be6f469c09574fa
...
Рейтинг: 0 / 0
15.02.2022, 19:54
    #40134357
godsql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Akina,

DISTINCT лишний
...
Рейтинг: 0 / 0
15.02.2022, 20:09
    #40134358
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Akina
Ролг Хупин
как одним запросом такое сделать для всех?

Не, а где эталонный (требуемый) результат для этих данных-то?


Эталона нет, но там интуитивно понятно, что должно быть
...
Рейтинг: 0 / 0
15.02.2022, 20:30
    #40134363
godsql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Ролг Хупин,

ну вот вам дали те 2 варианта решения, о которых я говорил в самом начале.
Результат-то похожий?
...
Рейтинг: 0 / 0
15.02.2022, 21:43
    #40134381
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
godsql
Ролг Хупин,

ну вот вам дали те 2 варианта решения, о которых я говорил в самом начале.
Результат-то похожий?


да, нет предела совершенству
...
Рейтинг: 0 / 0
15.02.2022, 22:46
    #40134392
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
godsql
DISTINCT лишний

Может, и лишний, а может и нет. Я не в курсе. Автор же считает, что "там интуитивно понятно, что должно быть" - вот пусть, если надо, интуитивно и убирает.
...
Рейтинг: 0 / 0
17.02.2022, 09:27
    #40134710
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Как можно простым человеческим фзыком объяснить, какой из запросов чем лучше?
Я как собака, какой-то лучше, но словами объяснить не могу

Из приведенных выше:
-- 1
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select * from @Products p inner join @SizeRanges1 n on p.Size between n.LimL1 and n.LimU1
union all
select * from @Products p inner join @SizeRanges2 n on p.Size between n.LimL2 and n.LimU2
union all
select p.*, '0' as LimL3,  '0' as LimU3, N'XEZ' as Description3  from @Products p where 
(
	not exists(select 1 from @SizeRanges2 n2 where p.Size between n2.LimL2 and n2.LimU2)
	and 
	not exists(select 1 from @SizeRanges1 n1 where p.Size between n1.LimL1 and n1.LimU1)
)



--2
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select P.*, ISNULL(S.Description1, 'XEZ') SIZE_DESC 
	from @Products P
OUTER APPLY 
(SELECT TOP 1 * FROM 
(
SELECT limL1, LimU1, Description1, 1 as N FROM @SizeRanges1 
UNION 
SELECT *, 2 FROM @SizeRanges2 
) T   WHERE P.Size between T.LimL1 and T.LimU1 
ORDER BY T.N
) S



--3
Код: sql
1.
2.
3.
4.
5.
6.
SELECT DISTINCT
       t0.*,
       COALESCE(t1.Description1, t2.Description2, 'XYZ') Description
FROM Products t0
LEFT JOIN SizeRanges1 t1 ON t0.size BETWEEN t1.LimL1 AND t1.LimU1
LEFT JOIN SizeRanges2 t2 ON t0.size BETWEEN t2.LimL2 AND t2.LimU2;
...
Рейтинг: 0 / 0
17.02.2022, 10:54
    #40134734
aleks222
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Третий лучче - он короче.

В 99% случаев - этот критерий (чем короче и проще - тем лучше ) правильный.
...
Рейтинг: 0 / 0
17.02.2022, 10:56
    #40134735
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
select
 p.*,
 coalesce(sr1.LimL1, sr2.LimL2, 'XEZ'),
 coalesce(sr1.LimU1, sr2.LimU2, 'XEZ')
from
 @Products p outer apply
 (select top (1) LimL1, LimU1, Description1 from @SizeRanges1 where p.size between LimL1 and LimU1) sr1 outer apply
 (select top (1) LimL2, LimU2, Description2 from @SizeRanges2 where sr1.LimL1 is null and p.size between LimL2 and LimU2) sr2
...
Рейтинг: 0 / 0
17.02.2022, 11:55
    #40134747
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать одним запросом?
aleks222
Третий лучче - он короче.

В 99% случаев - этот критерий (чем короче и проще - тем лучше ) правильный.


тоже так думаю, но хотел о других критериях почитать, от других юзеров.

Скажем, с точки зрения производительности, ясно, что не на таких данных, но теоретически
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как сделать одним запросом? / 21 сообщений из 21, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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