Почему SQL Server не соответствует математическим правилам BODMAS в SUM? - PullRequest
0 голосов
/ 06 июля 2018

Вчера я столкнулся с очень запутанной проблемой с унаследованной хранимой процедурой, и хотя я "исправил" ее, я не чувствую, что понимаю, зачем она нужна.

БОДМАС - Порядок математических операций:

Скобки, порядок, деление, умножение, сложение, вычитание

Итак, сложение происходит до вычитания. Технически они одинаково взвешены и происходят «одновременно», потому что они, как правило, противостоят друг другу.

С этим соглашением мы должны быть в состоянии согласиться с тем, что все следующее верно:

  • 1000 - (300 + 300) = 400
  • 1000 - 300 + 300 = 400
  • (1000 - 300) + 300 = 1000

Однако SQL оценивает средний как 1000. Я могу легко исправить это, добавив скобки. Я обеспокоен тем, что, хотя этот пример является чистым и простым, когда числа 300 приходят из объединенных сумм, вокруг уже есть много скобок. Вполне возможно, что они могут быть удалены случайно кем-то, кто следует логике BODMAS, или если они помечены как избыточные в оптимизаторе кода.

Вот код, который вы можете попробовать сами

CREATE TABLE #TempData ([Number] INT)

INSERT INTO #TempData VALUES(200)
INSERT INTO #TempData VALUES(100)

SELECT 1000 - (SUM(Number) + SUM(Number))
FROM #TempData

SELECT 1000 - SUM(Number) + SUM(Number)
FROM #TempData

SELECT (1000 - SUM(Number)) + SUM(Number)
FROM #TempData

DROP TABLE #TempData

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Ваша интерпретация BODMAS просто неверна. Умножение / деление и сложение / вычитание на самом деле не упорядочены, они эквивалентны и оцениваются слева.

Этот пункт специально рассматривается в Википедии:

Например, используя [BODMAS] в порядке добавления сначала, вычитание после "неправильно вычислит выражение [6]

10 − 3 + 2.

Правильное значение равно 9 (а не 5, как если бы сложение было перенесено первым, а результат используется с последующим вычитанием).

0 голосов
/ 06 июля 2018
1000 - 300 + 300 = 400

Это неправильно.

Как вы сказали, + и - одинаково взвешены и происходят одновременно. По соглашению, все основные операции являются ассоциативными слева, поэтому несколько операторов одного веса в строке обрабатываются слева направо:

1000 - 300 + 300 = ((1000 - 300) + 300

Это верно везде (математика, SQL, большинство языков программирования), поэтому проблема не в разнице между SQL и обычными математическими обозначениями, а в неправильном понимании соглашения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...