如果它们在另一列中共享一个值,如何从彼此中减去两行

时间:2015-12-17 12:45:38

标签: sql sql-server sql-server-2008

我目前正在使用以下结构的数据库中工作:

Var | Value | ID
--------------
  A |   1   | 1
  B |   2   | 1
  C |   3   | 1
  A |   2   | 2
  B |   4   | 2
  C |   6   | 2

我想要实现的是从与Var C共享相同ID的其他Var(B和C)中减去Var C的值。在这种情况下,输出将是:

Var | Value | ID
--------------
  A |  -2   | 1
  B |  -1   | 1
  C |   3   | 1
  A |  -4   | 2
  B |  -2   | 2
  C |   6   | 2

说实话,我完全不知道如何开始实现这个目标。我熟悉许多其他编程语言,但SQL仍然是困难/特定查询的挑战。

2 个答案:

答案 0 :(得分:3)

自我加入:

select t1.var,
       case when t1.var = 'C' then t1.value
            else t1.value - t2.value
       end as value,
       t1.id
from tablename t1
  join tablename t2 ON t1.id = t2.id
where t2.var = 'C'

请注意value是ANSI SQL中的保留字,因此应将其分隔为"Value"

答案 1 :(得分:1)

你可以预先分析“C”值然后用它来删除它们吗?

DECLARE @Data TABLE (
    [Var] VARCHAR(1),
    Value INT,
    ID INT);
INSERT INTO @Data SELECT 'A', 1, 1;
INSERT INTO @Data SELECT 'B', 2, 1;
INSERT INTO @Data SELECT 'C', 3, 1;
INSERT INTO @Data SELECT 'A', 2, 2;
INSERT INTO @Data SELECT 'B', 4, 2;
INSERT INTO @Data SELECT 'C', 6, 2;

WITH CValues AS (
    SELECT
        ID,
        Value
    FROM
        @Data
    WHERE
        [Var] = 'C')
SELECT
    d.[Var],
    CASE WHEN d.[Var] != 'C' THEN d.Value - c.Value ELSE d.Value END AS Value,
    d.ID
FROM
    @Data d
    LEFT JOIN CValues c ON c.ID = d.ID;

...但是,自我加入可能是一个更好的解决方案:

DECLARE @Data TABLE (
    [Var] VARCHAR(1),
    Value INT,
    ID INT);
INSERT INTO @Data SELECT 'A', 1, 1;
INSERT INTO @Data SELECT 'B', 2, 1;
INSERT INTO @Data SELECT 'C', 3, 1;
INSERT INTO @Data SELECT 'A', 2, 2;
INSERT INTO @Data SELECT 'B', 4, 2;
INSERT INTO @Data SELECT 'C', 6, 2;

SELECT
    d.[Var],
    CASE WHEN d.[Var] != 'C' THEN d.Value - c.Value ELSE d.Value END AS Value,
    d.ID
FROM
    @Data d
    LEFT JOIN @Data c ON c.[Var] = 'C' AND c.ID = d.ID;