Вероятно, наилучший способ сделать это - сохранить денормализованную версию данных.
ProductId, DelimitedList
1 ,323.113,5423.231,873.42,422.64,763.1,
Тогда ваш поиск прост
WHERE DelimitedList LIKE '%,323.113,5423.231,873.42,%'
Вы могли бы сначала выполнить стандартный запрос реляционного деления, чтобы вернуть те ProductId
значения, которые соответствуют всем значениям (не обязательно в правильном порядке или смежных), чтобы уменьшить количество строк, которые ищутся.
Полный демонстрационный скрипт
/*Set up test tables*/
CREATE TABLE Products(
ProductId int primary key)
CREATE TABLE ProductSegments(
ProductId int REFERENCES Products,
Sort int,
Value decimal(10,3)
Primary key (ProductId,Sort))
CREATE NONCLUSTERED INDEX ix ON ProductSegments(ProductId,Value)
CREATE TABLE ProductSegmentsDenormalized
(
ProductId int REFERENCES Products,
DelimitedList varchar(max)
)
/*Insert some initial data to Products...*/
INSERT INTO Products VALUES (1),(2),(3)
/*... and for ProductSegments*/
;WITH numbers(N)
AS (SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM master..spt_values v1,
master..spt_values v2)
INSERT INTO ProductSegments
(ProductId,
Sort,
Value)
SELECT ProductId AS Product,
n1.N Sort,
( ABS(CHECKSUM(NEWID()))% 1000000000 ) / 1000.00
FROM numbers n1,
Products
/*Set up table for search data*/
DECLARE @SearchValues TABLE
(
Sequence int primary key,
Value decimal(10,3)
)
INSERT INTO @SearchValues
VALUES (1,323.113),(2,5423.231),(3,873.420),(4,422.640),(5,763.100)
/*Fiddle the test data so we have some guaranteed matches*/
UPDATE ps
SET ps.Value = sv.Value
FROM ProductSegments ps
JOIN @SearchValues sv ON ProductId = 1 AND Sort = 100 + Sequence
UPDATE ps
SET ps.Value = sv.Value
FROM ProductSegments ps
JOIN @SearchValues sv ON ProductId = 3 AND Sort = 987 + Sequence
/*Create the denormalised data*/
INSERT INTO ProductSegmentsDenormalized
SELECT ProductId, '|' + DelimitedList
FROM Products p
CROSS APPLY ( SELECT CAST(Value as varchar) + '|'
FROM ProductSegments ps
WHERE ps.ProductId = p.ProductId
ORDER BY Sort
FOR XML PATH('') ) D ( DelimitedList )
/*Do the search*/
SELECT ProductId
FROM ProductSegmentsDenormalized psd
WHERE psd.ProductId IN (SELECT p.ProductId
FROM Products p
WHERE NOT EXISTS (SELECT *
FROM @SearchValues sv
WHERE NOT EXISTS
(SELECT *
FROM ProductSegments ps
WHERE ps.ProductId = p.ProductId
AND sv.Value = ps.Value)))
AND DelimitedList LIKE '%|' + (SELECT CAST(Value AS VARCHAR) + '|'
FROM @SearchValues sv
ORDER BY Sequence
FOR XML PATH('')) + '%'