Как получить ближайшее наименьшее число с помощью linq С#

У меня есть такая таблица sql,

SomeDouble      SomeInt
1.00              121
1.50              124
2.00              200
2.50              321

и так далее... до 10 000 для SomeDouble

Теперь у меня может быть десятичное число от 0,0 до 10 000,00, и мне нужно найти для него правильную строку. Например, если число равно 1,12, я хочу, чтобы оно возвращало 121.

1.49 должен вернуть 121, 1.50 должен вернуть 124, 1.51 должен вернуть 124.

Урезанная версия того, что я пытаюсь,

var myValue = 1.12
var SomeInt = (from mainTable in table1
                        join table3 in table2 on mainTable.someId equals table3.someId
                        where table3.Column1 == Column1 && mainTable.SomeDouble >= myValue
                        select mainTable.SomeInt).FirstOrDefault();

но мой вывод равен 124. Как я могу изменить выше, чтобы получить ближайшее наименьшее число, чем myValue ?

Должен ли where ... mainTable.SomeDouble >= myValue быть where ... mainTable.SomeDouble <=(FLIPPED) myValue, если вам нужен следующий smallest номер?

dvo 22.05.2019 15:16

Должна ли существовать запись в базе данных со значением SomeDouble, равным 0,00?

Andrew Morton 22.05.2019 15:30

@AndrewMorton наименьшее значение 0,50

Mathematics 22.05.2019 15:33

@Mathematics Мой комментарий о простом переключении <= не сработал? Он должен извлекать значение, которое является следующим наименьшим, а не следующим самым большим. Кроме того, ваш код выглядел хорошо для меня.

dvo 22.05.2019 15:54

@dvo это не работает

Mathematics 22.05.2019 16:02

@Математика, что она возвращает

dvo 22.05.2019 16:06
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
6
150
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

В SQL вы можете выразить ближайший как:

select t.*
from t
order by abs(SomeDouble - 1.12)
fetch first 1 row only;

Более эффективный метод сначала сузил бы его до двух строк:

select t.*
from ((select t.*
       from t
       where t <= 1.12
       order by SomeDouble desc
       fetch first 1 row only
      )  union all
      ((select t.*
       from t
       where t > 1.12
       order by SomeDouble asc
       fetch first 1 row only
      )
     ) t
order by (SomeDouble - 1.12)
fetch first 1 row only;

Использование запросов Linq:

        var above = (from mainTable in table1
            join table3 in table2 on mainTable.someId equals table3.someId
            where table3.Column1 == Column1 && mainTable.SomeDouble >= myValue
            orderby mainTable.SomeDouble
            select new {SomeInt = mainTable.SomeInt, SomeDouble = mainTable.SomeDouble}).FirstOrDefault();

        var below = (from mainTable in table1
            join table3 in table2 on mainTable.someId equals table3.someId
            where table3.Column1 == Column1 && mainTable.SomeDouble < myValue
            orderby mainTable.SomeDouble descending 
            select new {SomeInt = mainTable.SomeInt, SomeDouble = mainTable.SomeDouble}).FirstOrDefault();

        int SomeInt;
        if (above == null)
            SomeInt = below.SomeInt;
        else if (below == null)
            SomeInt = above.SomeInt;
        else if (Math.Abs(below.SomeDouble - myValue) <= Math.Abs(above.SomeDouble - myValue))
            SomeInt = below.SomeInt;
        else 
            SomeInt = above.SomeInt;

Если вы можете сделать это в SQL, то

SELECT COALESCE(MAX(SomeInt), 0)
FROM DoubleToInt
WHERE SomeDouble <= 1.12

Вот метод расширения linq для упорядочения записей по абсолютной разнице SomeDouble, затем по SomeInt, чтобы сначала получить наименьшее значение для 2 или более совпадений, а затем мы получаем первое. Похоже, что оба столбца существуют в основной таблице, поэтому я предполагаю, что мы можем сначала ограничить это, а затем присоединять к нему все, что вы хотите.

mainTable.OrderBy(x => Math.Abs(x.SomeDouble - myValue)).ThenBy(x => x.SomeInt).First()
Ответ принят как подходящий

Поскольку значения SomeDouble являются целыми и полуцелыми числами, вы можете округлить myValue до следующего кратного 0,5:

var myValueToLookUp = Math.Ceiling(myValue * 2) / 2;

а затем найдите значение SomeInt непосредственно с помощью mainTable.SomeDouble == myValueToLookUp, чтобы избежать путаницы или неэффективности с помощью <= или >=.

Другие вопросы по теме