2014-04-11 2 views
0

Предположим, у вас есть таблица (назовем его RulesTable), как это в SQL Server 2008 R2:Как написать SQL-запрос для получения ближайшего соответствия моим параметрам?

Id | Type | SubType1 | SubType2 | Value 
    1  A   A1   AA2  10 
    5  A   A1   NULL  50 
    2  A  NULL   AA3  20 
    3  A  NULL   NULL  30 
    4  NULL  NULL   NULL  40 

Я всегда будет запрашивать типа, SubType1, SubType2. Если один или несколько из них отсутствуют, то предположим, что оно NULL. Запрос всегда должен запрашивать в порядке Тип, SubType1, SubType2 и сузить поиск по мере его продвижения, а затем сопоставлять ближайшую запись. Итак, вот несколько сценариев использования:

(1) Если я запрашиваю для Type = 'A', SubType1 = 'B', SubType2 = 'C', тогда, поскольку 'B' или 'C' не найдены в таблице он должен использовать NULL для них. Поэтому я бы действительно искал Type = 'A', SubType1 = NULL, SubType2 = NULL, и я должен был бы получить значение 30 с ID = 3.

(2) Если я запрашиваю Type = 'A' , SubType1 = 'A1', SubType2 = 'C', тогда подтип2 должен = NULL, поскольку значение не находится в таблице, а ближайшее совпадение - Type = 'A', SubType1 = 'A1' и SubType2 = NULL, поэтому я должен закончить со значением = 50.

(3) Если я запрашиваю для Type = 'C', SubType1 = 'C', SubType3 = 'D', то, поскольку все эти значения не находятся в моей таблице, все они могут быть заменены на null так эффективно Я бы искал Type = NULL, SubType1 = NULL, SubType3 = NULL, поэтому я должен получить значение 40 или Id = 4

Так Предположим, у вас есть ParametersAndResultsTable:

MyId | Type | SubType1 | SubType2 | Id | Value 
    1  A  B   C  ?  ? 
    2  A  A1   C  ?  ? 
    3  C  C   D  ?  ? 

Так просто смотрю на идеи, как написать функцию для обновления ID/Значение в ParametersAndResultsTable (с использованием типа, SubType1, SubType2 в качестве параметров) и приведены данные RulesTable используя описанную выше логику. Имею в виду, может быть, посмотреть в расчет расстояние, но ищу идеи о том, как решить эту проблему ...

ответ

2

Это должно получить, что вы хотите, чтобы из наиболее точным наименее точным:

SELECT * 
FROM RulesTable 
WHERE ISNULL([Type], @Param1) = @Param1 
AND ISNULL(SubType1, @Param2) = @Param2 
AND ISNULL(SubType2, @Param3) = @Param3 
ORDER BY [Type] DESC, 
SubType1 DESC, 
SubType2 DESC 
+0

Так что я думаю, я бы чан e это значит «выбрать верх 1 *»? В противном случае, не будет ли это возвращать все наборы, которые потенциально приемлемы и не обязательно являются ближайшими? – Denis

+0

Правильно, вы можете включить «топ-1» в выборе, чтобы получить самую точную запись. – freakinthesun

1

Вот функция:

CREATE FUNCTION RuleTableFunction (@Type nvarchar(5), @SubType1 nvarchar(5), @SubType2 nvarchar(5)) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT 
     Id 
     ,Value 
    FROM 
     table_name 
    WHERE 
     (Type = @Type OR Type IS NULL) 
     and (SubType1 = @SubType1 OR SubType1 IS NULL) 
     and (SubType2 = @SubType2 OR SubType2 IS NULL) 
); 

для вызова функции:

SELECT * FROM RuleTableFunction ('A','B','C'); 
+0

Не будет ли это возвращать все приемлемые совпадения и не обязательно ближайший? – Denis

+0

Я думаю, что он делает то же самое в одно и то же время, он возвращает только строки, которые уважают «правила». Вы должны проверить его, чтобы убедиться, что это делает то, что вы хотите, и если соблюдаются «правила». Для меня это. – Ryx5