Как сделать пересечение SQL с табличным параметром?

Мне нужно сделать пересечение и получить общее variantID; из списка пар параметров (optionID,valueID).

Пример: для данного списка, в котором есть 2 элемента:

  • optionID = 16 и valueID = 1
  • optionID = 17 и valueID = 4

Я написал ниже запросы вручную:

select * 
from tbl_VariantValues
where optionID = 16 and valueID = 1 and productID = 399 

select * 
from tbl_VariantValues
where optionID = 17 and valueID = 4 and productID = 399

Я получаю следующие результаты:

productID  variantID  optionID  valueID
---------------------------------------
399        11         16        1
399        12         16        1
399        13         16        1
399        14         16        1
399        15         16        1

productID  variantID  optionID  valueID
---------------------------------------
399        13         17        4
399        19         17        4

Так как мне нужно только variantID, с пересечением:

select variantID 
from tbl_VariantValues
where optionID = 16 
  and valueID = 1 
  and productID = 319 

intersect 

select variantID 
from tbl_VariantValues
where optionID = 17 
  and valueID = 4 
  and productID = 319

Я получаю желаемый результат variantID: 13

Проблема в том, что я хочу выполнить вышеуказанный запрос программно, так как в списке tvp может быть больше элементов. Является ли это возможным?

Я попытался написать ниже запрос, но не знаю, где и как поставить пересечение:

create procedure [dbo].[getVariantID]
    (@list OptionValueList readonly)
as
begin 
    declare @UseTVP int
    set @UseTVP = (select count(*) from @list) 

    select variantID
    from dbo.tbl_VariantValues
    where (optionID = (select C.OptionID from @list C) 
      and valueID = (select C.OptionID, C.ValueID from @list C)
       or @UseTVP = 0)
    intersect
end

@UseTVP - это количество элементов tvp, мне нужна логика использования пересечения здесь для объединения таблиц. Или есть другой способ сделать это?


person Zeynep    schedule 20.04.2019    source источник
comment
То, что вы спросили, мне не ясно. Есть ли какая-то конкретная причина, по которой вы не получаете optionID, valueID и productID в качестве входных параметров внутри вашей хранимой процедуры?   -  person Masoud Keshavarz    schedule 20.04.2019
comment
@MasoudKeshavarz Поскольку в списке tvp будет n строк, будет n разных пар optionID, valueID для создания предложений where; Это означает, что запросов на выборку в sp будет n штук, и нужно поместить intersect между ними, чтобы получить variantID. Но запустить не смог. у меня синтаксическая ошибка..   -  person Zeynep    schedule 20.04.2019
comment
Я обновил свой ответ, если он не соответствует тому, что вы хотели, не могли бы вы оставить комментарий под моим ответом? Может быть, я мог бы отредактировать его, чтобы помочь вам. Спасибо.   -  person Masoud Keshavarz    schedule 20.04.2019
comment
@UseTVP is the count of the tvp items, I need a logic of intersect usage here to merge the tables. Как вы упомянули в своем вопросе, @UseTVP — это целое число, которое содержит количество записей tvp. Но что вы подразумеваете под «объединить таблицы»? Вы пытаетесь объединить результат с чем? Что вы имеете в виду под этой строкой: valueID=(SELECT C.OptionID, C.ValueID FROM @list C) OR @UseTVP = 0) Совершенно непонятно   -  person Masoud Keshavarz    schedule 20.04.2019
comment
@MasoudKeshavarz Просто я хочу поставить пересечение между таблицами, извините, если я не могу быть более ясным, я пытался объяснить на примере. Спасибо за Ваш ответ   -  person Zeynep    schedule 20.04.2019
comment
Вы пытаетесь присоединиться к @list с tbl_VariantValues? Является ли @Squirrel ответом на то, что вы ищете?   -  person Masoud Keshavarz    schedule 20.04.2019


Ответы (1)


Один из вариантов — использовать динамический SQL для создания запроса с несколькими операторами пересечения.

Или просто используйте JOIN для VariantValues ​​с OptionValue. Затем используйте GROUP BY + HAVING, чтобы все значения OptionValue соответствовали пользователю.

; with 
--  generate sample table tbl_VariantValues
tbl_VariantValues as
(
    select  productID = 399, variantID = 11, optionID = 16, valueID = 1 union all
    select  productID = 399, variantID = 12, optionID = 16, valueID = 1 union all
    select  productID = 399, variantID = 13, optionID = 16, valueID = 1 union all
    select  productID = 399, variantID = 14, optionID = 16, valueID = 1 union all
    select  productID = 399, variantID = 15, optionID = 16, valueID = 1 union all

    select  productID = 399, variantID = 13, optionID = 17, valueID = 4 union all
    select  productID = 399, variantID = 14, optionID = 17, valueID = 4 union all
    select  productID = 399, variantID = 19, optionID = 17, valueID = 4 union all

    select  productID = 399, variantID = 13, optionID = 18, valueID = 5 union all
    select  productID = 399, variantID = 15, optionID = 18, valueID = 5 union all
    select  productID = 399, variantID = 19, optionID = 18, valueID = 5
),
--  your OptionValue sample
OptionValueList  as
(
    select  productID = 399, optionID = 16, valueID = 1 union all
    select  productID = 399, optionID = 17, valueID = 4 union all
    select  productID = 399, optionID = 18, valueID = 5
)
--  the query
select  v.variantID
from    tbl_VariantValues v
        inner join OptionValueList o    on  v.productID = o.productID
                                       and  v.optionID  = o.optionID
                                       and  v.valueID   = o.valueID
group by v.variantID
having count(*) = (select count(*) from OptionValueList )
person Squirrel    schedule 20.04.2019
comment
Я не мог понять верхнюю часть вашего кода, но запрос, который вы написали внизу, работает. Спасибо! - person Zeynep; 20.04.2019
comment
Я имею в виду, над частью - person Zeynep; 20.04.2019
comment
эта часть предназначена только для меня, чтобы создать образцы данных, которых у меня нет. Для вас требуется только the query и замените переменную таблицы на ваше фактическое имя таблицы - person Squirrel; 20.04.2019