2d словарь или справочная таблица?

Я не совсем уверен, как назвать то, что мне нужно.

У меня есть эти данные в файле CSV и в базе данных SQL. Что мне нужно сделать, так это уметь использовать таблицу для билинейной интерполяции. Итак, когда говорят, что d = 2.5 и HVL = 1.6, как лучше всего это решить? Расчет, который я могу выполнить, просто не уверен, как выбрать соответствующие числа из таблицы, какой-то форме оператора LINQ?

Редактировать:

С цифрами 1.6 и 2.5 мне нужно выбрать числа, окружающие его, как матрицу 2x2 ( билинейная интерполяция)

Спасибо

1 ответ

Решение

1) Я взял небольшую часть вашей матрицы, которая выглядит так:

2) Затем мы берем ваш matix и динамически нормализуем его (см. Cte0), и это выглядит так:

Теперь, для повышения производительности, если это статическая матрица, я бы порекомендовал вам на самом деле хранить данные именно так.

3) Учитывая ваши целевые значения @X и @Y, нам нужно определить нужные строки и столбцы (в cte1). Результат выглядит так:

  • Поля и значения являются желаемыми номерами строк / столбцов.

4) В cte2 мы хотим получить диапазоны и значения X/Y, и это выглядит так:

4) Последний запрос - это небольшой вопрос интерполяции диапазонов / значений X/Y. Я использовал UDF только для облегчения математики.

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

ОК, а как насчет кода?

Я должен добавить, что я оставил эти части как cte, чтобы вы могли видеть, как отдельные части работают вместе. Конечно, это может быть сжато дальше (см. Изменить ниже).

Declare @YourTable Table ([y] int,[x1.5] float,[x2.0] float,[x3.0] float,[x4.0] float)
Insert Into @YourTable Values
 (1,1.050,1.055,1.057,1.057)
,(2,1.080,1.089,1.097,1.098)
,(3,1.091,1.103,1.114,1.446)

Declare @XML xml = (Select * from @YourTable for XML Raw) 
Declare @Y float = 2.5
Declare @X float = 1.6

;with cte0 as (
                Select RowNr = Dense_Rank() over (Order By r.value('@y','float'))
                      ,ColNr = Dense_Rank() over (Order By convert(float,replace(attr.value('local-name(.)','varchar(100)'),'x','')))
                      ,Y     = r.value('@y','float')
                      ,X     = convert(float,replace(attr.value('local-name(.)','varchar(100)'),'x',''))
                      ,V      = attr.value('.','float') 
                 From  @XML.nodes('/row') as A(r)
                 Cross Apply A.r.nodes('./@*') AS B(attr)
                 Where attr.value('local-name(.)','varchar(100)') not in ('y') )
     ,cte1 as ( 
                Select *
                 From (Select R1=max(RowNr),R2=max(RowNr)+1 From  cte0 A where Y<@Y) A
                 Join (Select C1=max(ColNr),C2=max(ColNr)+1 From  cte0 A where X<@X) B
                   on 1=1
              )
     ,cte2 as (
                Select X1  = max(case when C=1 then X end)
                      ,X2  = max(case when C=2 then X end)
                      ,Y1  = max(case when R=1 then Y end)
                      ,Y2  = max(case when R=2 then Y end)
                      ,Q11 = max(case when R=1 and C=1 then V end)
                      ,Q12 = max(case when R=1 and C=2 then V end)
                      ,Q21 = max(case when R=2 and C=1 then V end)
                      ,Q22 = max(case when R=2 and C=2 then V end)
                 From (
                        Select *
                              ,R=Dense_Rank() over (Order By RowNr)
                              ,C=Dense_Rank() over (Order By ColNr)
                         From  cte0 A
                         Cross Join cte1
                         Where RowNr between R1 and R2
                           and ColNr between C1 and C2
                      ) A
              )
Select Value = [dbo].[udf-Stat-Interpolate](@Y,Y1,Y2,[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q11,Q12) ,[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q21,Q22) )
 From  cte2

Возвращает

Value
1.0876

И наконец, UDF, если интересно

CREATE Function [dbo].[udf-Stat-Interpolate] (@PosNr float,@PosMin float,@PosMax float,@ValMin float,@ValMax float)  
Returns Float as  
Begin 
   Return (((@PosNr-@PosMin)/(@PosMax-@PosMin)*(@ValMax-@ValMin)))+@ValMin
End

Редактировать - если матрица хранится, как показано выше (#2)

Declare @Y float = 2.5
Declare @X float = 1.6

Select Value = [dbo].[udf-Stat-Interpolate](@Y,Y1,Y2,[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q11,Q12),[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q21,Q22) )
 From (
        Select X1  = max(case when C=1 then X end)
              ,X2  = max(case when C=2 then X end)
              ,Y1  = max(case when R=1 then Y end)
              ,Y2  = max(case when R=2 then Y end)
              ,Q11 = max(case when R=1 and C=1 then V end)
              ,Q12 = max(case when R=1 and C=2 then V end)
              ,Q21 = max(case when R=2 and C=1 then V end)
              ,Q22 = max(case when R=2 and C=2 then V end)
        From (
               Select *
                     ,R=Dense_Rank() over (Order By RowNr)
                     ,C=Dense_Rank() over (Order By ColNr)
                From  YourTable A
                Cross Join (
                            Select *
                             From (Select R1=max(RowNr),R2=max(RowNr)+1 From  YourTable A where Y<@Y) A
                             Join (Select C1=max(ColNr),C2=max(ColNr)+1 From  YourTable A where X<@X) B on 1=1
                           ) B
                Where RowNr between R1 and R2
                  and ColNr between C1 and C2
            ) A
      ) A
Другие вопросы по тегам