基于行中的键从表中划分/求和值

时间:2014-06-17 02:32:47

标签: sql sql-server tsql

您好我目前有一个表,有一个列值,我想用预定义的逻辑分割

    Table 1

   ID     Column X    Column Y      
   1      X1          7           
   2      x1          0           
   3      x1          0            
   4      x1          0           
   5      x1          0           
   6      x2          2           
   7      x2          0           
   8      x2          0        
   9      x3          3           
   10     x3          0        
   11     x3          0           
   12     x4          7            
   13     x4          0           
   14     x4          0   
   15     x5          2
   16     x5          0
   17     x5          0
   18     x5          0

Y列中的值将始终显示在第一行

有三种情况可以分割价值。

  1. 如果Y列中的值大于X列中的计数。该值将从上到下加1。示例:X1,X4

  2. 如果Y列中的值等于X列中的计数.YY列中的所有值都将为1.示例:X3

  3. 如果Y列中的值小于X列中的计数。该值将从上到下按因子0.5分割。将不存在所有0.5的总和将小于Y列中的值的情况。示例:X2,X5

    Wanted Result       
    ID     Column X    Column YY     
    1      X1          2
    2      x1          2
    3      x1          1
    4      x1          1
    5      x1          1
    6      x2          0.5
    7      x2          0.5
    8      x2          1
    9      x3          1           
    10     x3          1           
    11     x3          1           
    12     x4          3           
    13     x4          2         
    14     x4          2           
    15     x5          0.5
    16     x5          0.5
    17     x5          0.5
    18     x5          0.5
    

1 个答案:

答案 0 :(得分:2)

这是一项有趣的练习。需要窗口功能,所以应该是SS 2005及以上。必须看到更多的数据,看看我的逻辑是否在任何地方破坏。这是一个小提琴:http://sqlfiddle.com/#!3/32b9e/25

WITH cteBase
AS
(SELECT
          X,
          MAX(Y) AS MaxY,
          COUNT(*) AS Instances
 FROM
          Table1
 GROUP BY
          X),
cteValues
AS
(SELECT
          *,
          CASE
            WHEN MaxY < Instances THEN 0.5
            ELSE CEILING(MaxY * 1.00 / Instances * 1.00)
          END AS High,
          CASE
            WHEN MaxY < Instances AND (MaxY * 1.00) / (Instances * 1.00) % 0.5 = 0 THEN 0.5
            WHEN MaxY > Instances THEN MaxY / Instances 
            ELSE 1
          END AS Low
 FROM
          cteBase),
cteWithRowNums
AS
(SELECT
          t1.ID,
          ROW_NUMBER() OVER (PARTITION BY t1.X ORDER BY t1.ID) AS RowID,
          t1.X,
          v.High,
          v.Low,
          CASE
            WHEN MaxY < Instances THEN CEILING((MaxY * High) + 0.5)
            ELSE MaxY - (Instances * Low)
          END AS StartLowInstanceRowID
 FROM
          Table1 t1 INNER JOIN cteValues v
          ON t1.X = v.X
)

SELECT
          ID,
          X,
          CASE
              WHEN RowID <= StartLowInstanceRowID THEN High
              ELSE Low
          END AS YY
FROM 
          cteWithRowNums
ORDER BY
          ID;

编辑:清除了对X值分组和Y值递增的一些误解。更新了小提琴链接和代码。

编辑2:在处理MaxL&lt;的StartLowInstanceRowID时,我认为我的逻辑中出现了错误实例场景。有更新的代码和小提琴链接。