Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select) / 19 сообщений из 19, страница 1 из 1
08.02.2018, 14:10
    #39598999
ВладимирЛ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
Добрый день, Знатоки SQL!

Сейчас в интернете часто встречается использование групповых (или сгруппированных) фильтров.
Как по ним организовать выборку? Вот максимально упрощённый вариант T-SQL кода:

Код: 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.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
--Главная таблица
Declare @tbMain table
(idMain int,   
 p1 int,
 p2 int )

			 Insert into @tbMain (idMain, p1,p2)
				  values (1,    100, 2017),
						 (2,    100, 2017),
						 (3,    200, 2017),
						 (4,    200, 2018)


--Таблица Фильтр
Declare @tbFilter table
		(idFilter int,  
		 nameFilter nvarchar(10),
		 value int)

			 Insert into @tbFilter (idFilter, nameFilter, value)
				  values (10,   'Код',100),
						 (20,   'Код',200),
						 (30,   'Год',2017),
						 (40,   'Год',2018)

--Таблица для связи (многие ко многим) Главной Таблицы и Таблицы Фильтра
Declare @tbManyToMany table
		(id int  identity (1,1),
		 idMain int,
		 idFilter int)

			 Insert into @tbManyToMany (idMain, idFilter)
				  values (1, 10),  --Фильтр по коду
                         (2, 10),  --Фильтр по коду
                         (3, 20),  --Фильтр по коду
                         (4, 20),  --Фильтр по коду

                         (1, 30),  --Фильтр по Году
                         (2, 30),  --Фильтр по Году
                         (3, 30),  --Фильтр по Году
                         (4, 40)   --Фильтр по Году


--Задаем Фильтр:
--Код   -> Указываем 100 и 200
--Год   -> Указываем 2017
--Результат должен быть   <Select * From @tbMain...+ where ...???>:
			--1	100	2017
			--2	100	2017
			--3	200	2017



--Вопрос - Как составить запрос в один запрос? Решается ли задача в один запрос?
--Пробовал варианты, но увы-ссс:



Select M.* From @tbMain As M
           inner join @tbManyToMany as MM on M.idMain = MM.idMain
		      inner join @tbFilter F on MM.idFilter = F.idFilter
where 
            (F.nameFilter = 'Код' and  F.value in (100, 200) )
			or --??? and ???
			(F.nameFilter = 'Год' and  F.value in (2017) )
...
Рейтинг: 0 / 0
08.02.2018, 14:44
    #39599035
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
ВладимирЛКак составить запрос в один запрос? Решается ли задача в один запрос?
Схематично:
Код: sql
1.
2.
3.
4.
5.
6.
SELECT m.*
FROM main m
JOIN properties p
WHERE (p.type, p.value) IN ( ('type1', 'value1'), .. , ('typeN', 'valueN') )
GROUP BY m.*
HAVING COUNT(*) = N
...
Рейтинг: 0 / 0
08.02.2018, 15:06
    #39599068
ВладимирЛ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
Akina, Уточнение-вопрос:
Конструкция

WHERE (p.type, p.value) IN ( ('type1', 'value1'), .. , ('typeN', 'valueN') )

вроде как не из T-SQL?
В "транзакте" с левой стороны IN допускается только один параметр(?).
...
Рейтинг: 0 / 0
08.02.2018, 15:06
    #39599069
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
AkinaВладимирЛКак составить запрос в один запрос? Решается ли задача в один запрос?
Схематично:
Код: sql
1.
2.
3.
4.
5.
6.
SELECT m.*
FROM main m
JOIN properties p
WHERE (p.type, p.value) IN ( ('type1', 'value1'), .. , ('typeN', 'valueN') )
GROUP BY m.*
HAVING COUNT(*) = N

В T-SQL так нельзя.
Однако, есть же EXISTS() и INTERSECT
...
Рейтинг: 0 / 0
08.02.2018, 15:08
    #39599073
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
iapОднако, есть же EXISTS() и INTERSECTМожет, даже NOT EXISTS(SELECT ... EXCEPT SELECT ... EXCEPT SELECT .........)
...
Рейтинг: 0 / 0
08.02.2018, 15:16
    #39599088
ВладимирЛ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
iap,
Вот так сработало:
Select M.* From @tbMain As M
inner join @tbManyToMany as MM on M.idMain = MM.idMain
inner join @tbFilter F on MM.idFilter = F.idFilter
where
(F.nameFilter = 'Код' and F.value in (100, 200) )
INTERSECT
Select M.* From @tbMain As M
inner join @tbManyToMany as MM on M.idMain = MM.idMain
inner join @tbFilter F on MM.idFilter = F.idFilter
where

(F.nameFilter = 'Год' and F.value in (2017) )

Но здесь все-таки два SELECT, а как в одном?
...
Рейтинг: 0 / 0
08.02.2018, 15:17
    #39599093
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
ВладимирЛКонструкция
Код: sql
1.
WHERE (p.type, p.value) IN ( ('type1', 'value1'), .. , ('typeN', 'valueN') )


вроде как не из T-SQL?
Вам слово "схематично" ни о чём не говорит? и да, в T-SQL это развернётся в показанное Вами же
ВладимирЛ
Код: sql
1.
2.
3.
4.
where 
(F.nameFilter = 'Код' and  F.value in (100, 200) )
or --??? and ???
(F.nameFilter = 'Год' and  F.value in (2017) )
...
Рейтинг: 0 / 0
08.02.2018, 15:19
    #39599097
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
ВладимирЛ,

можно же переписать запрос Akina с помощью явного сравнения пар type и value и операторов AND и OR.
Длинное будет условие, зато SELECT - один!
...
Рейтинг: 0 / 0
08.02.2018, 15:30
    #39599116
ВладимирЛ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
Akina,
Да, спасибо за ответ. На "схематично" я, конечно, обратил внимание. Но если бы все было так просто, я бы не задавал вопрос.
Упрощаем запрос до одной таблицы:

Select M.* From @tbMain As M
where p1 in (100,200)
and p2 in (2017)

И вот так работает, поскольку условие наложено на два поля таблицы.
А в том, что я написал - условие накладывается на (схематично) одно поле, поэтому по or оно возвращает больше, чем надо, а по and вообще ничего не возвращает. То есть, опять же схематично - сначала должен отработать первый фильтр, а потом на его результат належится следующий фильтр. Как это сделать одним SELECTом я не знаю. Возможно, задача не решаема.






Там нюанс в том, что используется
...
Рейтинг: 0 / 0
08.02.2018, 15:41
    #39599137
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
ВладимирЛпо or оно возвращает больше, чем надоТо есть группировку и пост-отбор Вы в моей схеме не увидели? а именно они обеспечивают решение задачи.
...
Рейтинг: 0 / 0
08.02.2018, 15:51
    #39599152
ВладимирЛ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
Akina,

Ну вот запрос с группировкой:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
Select M.idMain, M.p1, M.p2 From @tbMain As M
           inner join @tbManyToMany as MM on M.idMain = MM.idMain
		      inner join @tbFilter F on MM.idFilter = F.idFilter
where 
            (F.nameFilter = 'Код' and  F.value in (100, 200) )
			or --??? and ???
			(F.nameFilter = 'Год' and  F.value in (2017) )
group by  M.idMain, M.p1, M.p2




Возвращает:

1 100 2017
2 100 2017
3 200 2017
4 200 2018


А годик то указан 2017 ???? Вот в этом и заковыка.
...
Рейтинг: 0 / 0
08.02.2018, 15:52
    #39599156
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
Нет, вот что Вы хотите, если у Вас в списке вывода - уникальный индекс???
...
Рейтинг: 0 / 0
08.02.2018, 15:53
    #39599158
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
Да и HAVING я как-то не наблюдаю...
...
Рейтинг: 0 / 0
08.02.2018, 16:04
    #39599179
ВладимирЛ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
Akina,
Без "ключа" вот так:
100 2017
200 2017
200 2018

то есть 2018 все равно есть, поэтому "оно" не принципиально.
А что даёт это условие:

HAVING COUNT(*) = N

в частности я не совсем понимаю параметр N. (в T-SQL такого нет)
...
Рейтинг: 0 / 0
08.02.2018, 16:32
    #39599231
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
ВладимирЛв частности я не совсем понимаю параметр NОбрати внимание на условие отбора - там указаны наборы условий с номерами от 1 до N. Вот это N и должно быть в запросе.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
Select M.p1, M.p2 
From @tbMain As M
inner join @tbManyToMany as MM on M.idMain = MM.idMain
inner join @tbFilter F on MM.idFilter = F.idFilter
where (F.nameFilter = 'Код' and  F.value in (100, 200) ) -- условие по первому параметру
   or
      (F.nameFilter = 'Год' and  F.value in (2017) ) -- условие по второму параметру
group by  M.p1, M.p2
HAVING COUNT(*) = 2 -- всего параметров - два
...
Рейтинг: 0 / 0
08.02.2018, 16:50
    #39599254
ВладимирЛ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
Akina, Спасибо за ответ, осмысливаю. Вообще то -
COUNT(*) - это количество записей по возвращаемым строкам группировки и как оно связано с номером условий? В общем пока непонятно, осмысливаю.
...
Рейтинг: 0 / 0
08.02.2018, 16:56
    #39599261
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
ВладимирЛкак оно связано с номером условий?не с номером, а с их количеством. Тебе же надо, чтобы запись соответствовала ВСЕМ фильтрам? COUNT(*) тебе как раз и показывает, сколько фильтров из всех соответствуют.
...
Рейтинг: 0 / 0
08.02.2018, 17:06
    #39599272
ВладимирЛ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
Akina,
Вот запрос:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Select 
 M.p1, M.p2
 , COUNT(*) as count
  From @tbMain As M
           inner join @tbManyToMany as MM on M.idMain = MM.idMain
		      inner join @tbFilter F on MM.idFilter = F.idFilter
where 
            (F.value in (100, 200) )
		     or --??? and ???
			(F.value in (2017) )
group by  
 M.p1, M.p2
  -- HAVING COUNT(*) = 2




Вот его результат:

100 2017 4
200 2017 2
200 2018 1

Правый столбец - это и есть количество возвращаемых записей по группировке "M.p1, M.p2". С количеством условий вроде как никак не связано.
...
Рейтинг: 0 / 0
12.02.2018, 16:10
    #39600697
Maxx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
select t1.*
from @tbMain t1
 inner join @tbFilter f1 on t1.p1 =f1.value
 inner join @tbFilter f2 on f2.value =t1.p2
where f1.nameFilter =N'Код'
  and f2.nameFilter = N'Год'
  and t1.p2 =2017
  and t1.p1 in (100,200)
  and exists (
      select 1
	  from @tbManyToMany
	  where t1.idMain =idMain
	    and ISNULL(f1.idFilter,f2.idFilter) = idFilter
  )
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Выборка по групповым фильтрам (простой вопрос Знатокам SQL по обычному Select) / 19 сообщений из 19, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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