SQL Server:使用先前行中相同列的值计算列的值

时间:2016-12-21 04:13:35

标签: sql sql-server

我有一张看起来像的表,

CREATE TABLE #tmpPercentage
( 
    ID INT,
    V1 VARCHAR(10),
    V2 FLOAT
);

INSERT INTO #tmpPercentage (ID, V1, V2)
VALUES (1, 'X', 10),
       (1, 'Y', 7),
       (1, 'Z', ?),
       (2, 'X', 15),
       (2, 'Y', 19),
       (2, 'Z', ?);

Z的V2将是(V2 for X * V2 for Y)/100,即x和y之间的百分比。

我该如何计算?我是SQL的新手。提前致谢

5 个答案:

答案 0 :(得分:0)

XY条记录转移到每个ID的列中,然后进行计算

这是一种方式

select ID,
       Z = (max(case when V1 = 'X' then V2 end) * max(case when V1 = 'Y' then V2 end))/100.0
From #tmpPercentage
Group by ID

以上Select可以转换为Update查询

;WITH cte
     AS (SELECT ID,
                Z = ( Max(CASE WHEN V1 = 'X' THEN V2 END) * Max(CASE WHEN V1 = 'Y' THEN V2 END) ) / 100.0
         FROM   #tmpPercentage
         GROUP  BY ID)
UPDATE t
SET    V2 = c.z
FROM   #tmpPercentage t
       JOIN cte c
         ON t.ID = c.ID
WHERE  v1 = 'Z' 

考虑到每个X只有一个YID值。如果X的值超过YID,则将Max汇总为SumAvgMin根据您的要求。

答案 1 :(得分:0)

CREATE TABLE #tmpPercentage
( ID INT,
  V1 VARCHAR(10),
  V2 FLOAT);

INSERT INTO #tmpPercentage
(ID, V1, V2)
VALUES (1, 'X', 10),
       (1, 'Y', 7),
       (2, 'X', 15),
       (2, 'Y', 19),

然后,分别为Z执行插入:

insert into #tmpPercentage
select id, 'Z', 
(max(case when V1 = 'X' then V2 end) * max(case when V1 = 'Y' then V2 end))/100.0
from #tmpPercentage
group by id, 'Z';

答案 2 :(得分:0)

; WITH tmpPercentage (ID,V1, V2) AS (
  SELECT 1, 'X', 10 UNION ALL
  SELECT 1, 'Y', 7  UNION ALL
  SELECT 1, 'Z', NULL UNION ALL
  SELECT 2, 'X', 15 UNION ALL
  SELECT 2, 'Y', 19 UNION ALL
  SELECT 2, 'Z', NULL
  )
  SELECT ID, MAX(CASE WHEN v1='X' THEN V2 ELSE 0 END) *  MAX(CASE WHEN v1='Y' THEN V2 ELSE 0 END)/100.0 AS Z FROM tmpPercentage
  GROUP BY ID
ID          Z
----------- ---------------------------------------
1           0.700000
2           2.850000
  SELECT ID,V1,CASE WHEN V1='Z' THEN  
          MAX(CASE WHEN v1='X' THEN V2 ELSE 0 END) OVER(PARTITION BY ID)
        * MAX(CASE WHEN v1='Y' THEN V2 ELSE 0 END)OVER(PARTITION BY ID)/100.0 ELSE V2 END  AS V2 
  FROM tmpPercentage
ID          V1   V2
----------- ---- ---------------------------------------
1           Y    7.000000
1           Z    0.700000
1           X    10.000000
2           Y    19.000000
2           Z    2.850000
2           X    15.000000

答案 3 :(得分:0)

您可以使用下面的CTE来处理此问题,而无需更改记录的顺序以及单个INSERT语句和UPDATE语句。

注意:只需将以下语句复制并粘贴到您的本地计算机上,然后尝试一下它就像魅力一样: - )

CREATE TABLE #tmpPercentage
( ID INT,
  V1 VARCHAR(10),
  V2 FLOAT);


;WITH tmpPercentage0 AS (
   SELECT 1 AS ID, 'X' AS V1, 10 AS V2
   UNION
   SELECT 1 AS ID, 'Y' AS V1, 7 AS V2
   UNION
   SELECT 1 AS ID, 'Z' AS V1, NULL AS V2
   UNION
   SELECT 2 AS ID, 'X' AS V1, 15 AS V2
   UNION
   SELECT 2 AS ID, 'Y' AS V1, 19 AS V2
   UNION
   SELECT 2 AS ID, 'Z' AS V1, NULL AS V2
),
tmpPercentage1 AS (
    SELECT 
        *, ROW_NUMBER() OVER (ORDER BY ID) AS RowNumber
    FROM  
        tmpPercentage0
)

INSERT INTO #tmpPercentage
    (ID,
     V1,
     V2)
SELECT 
    ID, V1, (
    CASE
        WHEN V1 = 'Z' THEN (
            (
                (SELECT CONVERT(FLOAT, V2) FROM tmpPercentage1 WHERE RowNumber = tp1.RowNumber - 2)
                *
                (SELECT CONVERT(FLOAT, V2) FROM tmpPercentage1 WHERE RowNumber = tp1.RowNumber - 1)
            ) / 100
        )
        ELSE V2
    END) AS V2
FROM 
    tmpPercentage1 tp1

答案 4 :(得分:0)

如果您使用的是较新版本的sql-server(例如2012),则可以使用 LAG 功能,该功能可以返回上一行 -

SELECT ID, V1
    , CASE
        WHEN V1 = 'Z'
        THEN ((LAG (V2, 1) OVER (PARTITION BY ID ORDER BY V1)) * (LAG (V2, 2) OVER (PARTITION BY ID ORDER BY V1))) / 100
        ELSE V2
      END AS V2
FROM #tmpPercentage;

下面

((LAG (V2, 1) and LAG (V2, 2)

分别返回当前行之前的V2和前两行的V2。

OVER (PARTITION BY ID ORDER BY V1))

这确保了我们首先使用PARTITION BY在每个ID上应用LAG 然后在ORDER BY子句上使用V1对x,y,z中的行进行排序。因此,对于z存在所有x,y是很重要的。但是,即使对于随机排序的数据,此查询也会返回正确的结果 -

INSERT INTO #tmpPercentage
(ID, V1, V2)
VALUES (1, 'X', 10),
       (2, 'X', 15),
       (1, 'Z', NULL),
       (2, 'Y', 19),
       (2, 'Z', NULL),
       (1, 'Y', 7);

<强>输出

| ID | V1 | V2   |
|----|----|------|
| 1  | X  | 10   |
| 1  | Y  | 7    |
| 1  | Z  | 0.7  |
| 2  | X  | 15   |
| 2  | Y  | 19   |
| 2  | Z  | 2.85 |

注意:此查询应该比使用子查询的任何其他版本更快。