powered by simpleCommunicator - 2.0.27     © 2024 Programmizd 02
Map
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как сделать одним запросом?
21 сообщений из 21, страница 1 из 1
Как сделать одним запросом?
    #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
Как сделать одним запросом?
    #40134330
godsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нифига не понял, что мешает использовать два раза Left join, а потом отфильтровать пустышки
Или обычный Union хоть по двум результатам, хоть запрос по результату union
...
Рейтинг: 0 / 0
Как сделать одним запросом?
    #40134332
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
godsql
Нифига не понял, что мешает использовать два раза Left join, а потом отфильтровать пустышки


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


Нет, не одно слово селект, естественно.
...
Рейтинг: 0 / 0
Как сделать одним запросом?
    #40134339
godsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
там все-таки пересекаются диапазоны.
Тогда ID таблицы нужно использовать
...
Рейтинг: 0 / 0
Как сделать одним запросом?
    #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
Как сделать одним запросом?
    #40134343
godsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
не заметил пересечений.
чуть по-позже напишу
...
Рейтинг: 0 / 0
Как сделать одним запросом?
    #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
Как сделать одним запросом?
    #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
Как сделать одним запросом?
    #40134353
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг Хупин
как одним запросом такое сделать для всех?

Не, а где эталонный (требуемый) результат для этих данных-то?
...
Рейтинг: 0 / 0
Как сделать одним запросом?
    #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
Как сделать одним запросом?
    #40134357
godsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,

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

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


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

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

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


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

Может, и лишний, а может и нет. Я не в курсе. Автор же считает, что "там интуитивно понятно, что должно быть" - вот пусть, если надо, интуитивно и убирает.
...
Рейтинг: 0 / 0
Как сделать одним запросом?
    #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
Как сделать одним запросом?
    #40134734
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Третий лучче - он короче.

В 99% случаев - этот критерий (чем короче и проще - тем лучше ) правильный.
...
Рейтинг: 0 / 0
Как сделать одним запросом?
    #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
Как сделать одним запросом?
    #40134747
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aleks222
Третий лучче - он короче.

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


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

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


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