покритикуйте запрос
От: Kaifa Россия  
Дата: 18.03.18 04:32
Оценка:

Даны 2 набора данных вида:

DECLARE  @Свойства TABLE (Лицевой INT, Параметр INT, Значение INT);
INSERT INTO @Свойства
VALUES   (1,1,1)
        ,(1,2,1)
        ,(1,1,5)
        ,(2,1,1)
        ,(2,1,5)
        ,(2,2,7);

DECLARE  @filter TABLE (Параметр INT,Значение INT)
INSERT INTO @filter 
VALUES (1,5),(2,7);


Задача: Найти такие значения @Свойства.Лицевой, для которых выполняется условие фильтра по параметрам:
Все комбинации Параметр/Значение, содержащиеся в наборе @filter обязательно присутствуют на таких лицевых. Наличие других параметров или других значений для указанных параметров не имеет значения.


два варианта придумал по большому счету аналогичных:


[sql]
select
sv.Лицевой
from (
    select distinct Лицевой, Параметр, Значение from @Свойства
) sv
join (
    select distinct
        f.Параметр as par,
        f.Значение as val
    from @filter f
) s on s.par = sv.Параметр and s.val = sv.Значение
group by sv.Лицевой 
having count(1) = (
    select count(1) from (
        select count(1) cnt from @filter 
        group by Параметр, Значение
) s )


DECLARE  @СвойстваUq TABLE (Лицевой INT, Параметр INT, Значение INT)
insert into @СвойстваUq(Лицевой, Параметр, Значение)
select distinct Лицевой, Параметр, Значение from @Свойства

DECLARE  @filterUq TABLE (Параметр INT,Значение INT)
insert into @filterUq 
select distinct Параметр, Значение from @filter

declare @filterCnt int
select @filterCnt = count(1) from @filterUq

select
sv.Лицевой
from @СвойстваUq sv
join @filterUq f on f.Значение = sv.Значение and f.Параметр = sv.Параметр
group by sv.Лицевой
having count(1) = @filterCnt
Re: покритикуйте запрос
От: rm822 Россия  
Дата: 18.03.18 09:45
Оценка:
Это стандартная задача, известна как "Relational division"
вариантов решения много
критиковать смысла нет

https://www.red-gate.com/simple-talk/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/
https://www.red-gate.com/simple-talk/sql/learn-sql-server/high-performance-relational-division-in-sql-server/
Re: покритикуйте запрос
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.03.18 10:02
Оценка:
Здравствуйте, Kaifa, Вы писали:

K>
K>DECLARE  @СвойстваUq TABLE (Лицевой INT, Параметр INT, Значение INT)
K>insert into @СвойстваUq(Лицевой, Параметр, Значение)
K>select distinct Лицевой, Параметр, Значение from @Свойства

K>DECLARE  @filterUq TABLE (Параметр INT,Значение INT)
K>insert into @filterUq 
K>select distinct Параметр, Значение from @filter

K>declare @filterCnt int
K>select @filterCnt = count(1) from @filterUq

K>select
K>sv.Лицевой
K>from @СвойстваUq sv
K>join @filterUq f on f.Значение = sv.Значение and f.Параметр = sv.Параметр
K>group by sv.Лицевой
K>having count(1) = @filterCnt
K>

Нормальный вариант. Непонятно только, для чего делать копию данных. Достаточно просто уровень изоляции выставить подходящий.
Ну, или просто посчитать каунт в рамках стейтмента:
select
sv.Лицевой
from @Свойства sv
join @filter f on f.Значение = sv.Значение and f.Параметр = sv.Параметр
group by sv.Лицевой
having count(1) = (select count(1) from @filter)
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 19.03.2018 0:59 Sinclair . Предыдущая версия .
Re[2]: В России опять напишут новый объектно-ориентированны
От: Kaifa Россия  
Дата: 18.03.18 15:34
Оценка:
S>select
S>sv.Лицевой
S>from @Свойства sv
S>join @filter f on f.Значение = sv.Значение and f.Параметр = sv.Параметр
S>group by sv.Лицевой
S>having count(1) = (select count(1) from @filter)

не сработает, если есть дублирующиеся значения в фильте или свойствах. например:
DECLARE  @Свойства TABLE (Лицевой INT, Параметр INT, Значение INT);
INSERT INTO @Свойства
VALUES   (1,1,1)
        ,(1,2,1)
        ,(1,1,5)
        
,(1,1,5)
        ,(2,1,1)
        ,(2,1,5)
        ,(2,2,7)
        ,(2,2,7)
        ,(2,2,7)

DECLARE  @filter TABLE (Параметр INT,Значение INT)
INSERT INTO @filter 
VALUES (1,5),(2,7), (2,7), (1, 1);
Re[3]: В России опять напишут новый объектно-ориентированны
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.03.18 00:58
Оценка:
Здравствуйте, Kaifa, Вы писали:


S>>select

S>>sv.Лицевой
S>>from @Свойства sv
S>>join @filter f on f.Значение = sv.Значение and f.Параметр = sv.Параметр
S>>group by sv.Лицевой
S>>having count(1) = (select count(1) from @filter)

K>не сработает, если есть дублирующиеся значения в фильте или свойствах.

Решается unique constraint. Если есть веская причина хранить дубли, то надо уточнять задачу — как именно надо подсчитывать вхождения.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.