Условное вычитание строки - PullRequest
1 голос
/ 02 марта 2012

Я использую SQL Server 2005.

У меня есть два столбца а и б.

Я хочу вычесть b из a, чтобы получить c, что я делаю следующим образом:

a - b as c

но я хочу дополнить это тем, что c = 0, если a или b равно 0. Как мне это сделать?

Спасибо

Барри

Ответы [ 5 ]

3 голосов
/ 02 марта 2012

Попробуйте использовать чехол

SELECT 
   CASE WHEN a = 0 OR b = 0 
        THEN 0 
        ELSE a - b 
   END c

Подробнее об этом

http://msdn.microsoft.com/en-us/library/ms181765.aspx

2 голосов
/ 02 марта 2012

Использование оператора CASE определенно является наиболее рекомендуемым способом, но для удовольствия и удовольствия использование некоторого сдвига битов также будет работать

c = ABS(a - b) 
    * (((CAST(ABS(a * b) AS BIGINT)+0x7FFFFFFF)) 
    / POWER(2, 16) / POWER(2, 15))

Предпринятые шаги

  1. Умножьте, чтобы получить либо нулевое (a или b равно нулю), либо ненулевое (a и b оба <> 0) значение. Ненулевое значение необходимо преобразовать в 1

    ABS(a * b)

  2. Приведение к BIGINT для предотвращения Arithmetic overflow

    CAST(ABS(a * b) AS BIGINT)

  3. Убедитесь, что бит 32 установлен в 1, если ABS(a * b) было ненулевым значением.

    CAST(ABS(a * b) AS BIGINT)+0x7FFFFFFF

  4. Сдвиг на 31 бит, сохраняя либо 0, либо 1. (Поскольку POWER возвращает int, это нужно сделать в два шага вместо более простого POWER (2, 31))

    ((CAST(ABS(a * b) AS BIGINT)+0x7FFFFFFF))
    / POWER(2, 16) / POWER(2, 15)

  5. Умножьте исходное уравнение на наши расчетные 0 или 1.

    ABS(a - b)
    * (((CAST(ABS(a * b) AS BIGINT)+0x7FFFFFFF))
    / POWER(2, 16) / POWER(2, 15))

Тестовый скрипт

;WITH q (a, b) AS (
  SELECT * FROM (VALUES
      (0, 0)
    , (0, 1)
    , (0, 2)
    , (1, 0)
    , (1, 1)
    , (1, 2)
    , (2, 0)
    , (2, 1)
    , (2, 2)
    , (9, 0)
    , (9, 1)
    , (9, 2)
  ) a (b, c)
)
SELECT  a
        , b
        , c = ABS(a - b) 
              * (((CAST(ABS(a * b) AS BIGINT)+0x7FFFFFFF)) 
              / POWER(2, 16) / POWER(2, 15))
FROM    q

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

Как и в комментариях, мы задались вопросом о различиях в производительности, ниже приведена быстрая настройка теста.

Настройка теста производительности

CREATE TABLE q (a INTEGER, b INTEGER)
;WITH numbers (a) AS (
    SELECT  0
    UNION ALL 
    SELECT  a + 1
    FROM    numbers
    WHERE   a < 999
)
INSERT  INTO q
SELECT  a1.a, a2.a
FROM    numbers a1
        CROSS APPLY numbers a2
OPTION (MAXRECURSION 0)         

Тест производительности

SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT  c = (a - b)
              * (((CAST(ABS(a * b) AS BIGINT)+0x7FFFFFFF)) 
              / POWER(2, 16) / POWER(2, 15))
FROM    q

SELECT 
   CASE WHEN a = 0 OR b = 0 
        THEN 0 
        ELSE a - b 
   END c
FROM    q   
0 голосов
/ 02 марта 2012
SELECT a, b,    
       COALESCE(NULLIF(a, 0) - NULLIF(b, 0), 0) AS c
  FROM T1;

Или

SELECT a, b, 0 AS c
  FROM T1
 WHERE 0 IN (a, b)
UNION
SELECT a, b, a - b AS c
  FROM T1
 WHERE 0 NOT IN (a, b);

Обратите внимание, что каждый обрабатывает нули по-разному (в спецификации не указано, как обрабатывать нули).

0 голосов
/ 02 марта 2012

Попробуйте его:

 SELECT 
 a,b,
 CASE
    WHEN a = 0 OR  b = 0 THEN 0
    ELSE
       a - b
 END AS c
 FROM table
0 голосов
/ 02 марта 2012

Ну, это должно сделать это:)

SELECT
 CASE WHEN A=0 OR B=0 THEN 0 ELSE A-B END AS C
FROM 
 TABLE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...