在SQL中使用固定阈值将最大/最小分数拆分为3个波段

时间:2012-06-22 14:42:46

标签: tsql

考虑到最大/最小分数90-22,100-55,55-41,93-30,40-18,我需要将它们分成3个波段,每个波段的阈值分别为80和60.所以对于第一对这会给我(90-80,80-60,60-22),最后一对会给(null-80,null-60,40-18)。

我已经部分使用了下面的SQL,我遇到的问题是边缘情况,例如对于最后一对(40-18),UpperRed值返回为60.我知道我如果最大/最小分数不低于80(例如93-85,那么会有问题,因为这也会让我回到琥珀色范围,这是我不想要的)。

DECLARE @GreenLower INT
DECLARE @AmberUpper INT
DECLARE @AmberLower INT
DECLARE @RedUpper INT

SET @GreenLower = 80
SET @AmberUpper = 80
SET @AmberLower = 60
SET @RedUpper = 60

DECLARE @Scores TABLE
  (
   GroupedBy VARCHAR(50) ,
   PCTMax INT ,
   PCTAvg INT ,
   PCTMin INT ,
   ALLAvg INT ,
   AllMax INT ,
   AllMin INT
  )

INSERT  INTO @Scores
VALUES  ( 'Prov1', 80, 75, 63, 50, 90, 22 )
INSERT  INTO @Scores
VALUES  ( 'Prov2', 100, 96, 70, 80, 100, 55 )
INSERT  INTO @Scores
VALUES  ( 'Prov3', 72, 58, 44, 62, 85, 41 )
INSERT  INTO @Scores
VALUES  ( 'Prov4', 90, 78, 58, 59, 93, 30 )
INSERT  INTO @Scores
VALUES  ( 'Prov5', 63, 25, 21, 30, 40, 18 )

SELECT  GroupedBy ,
            PCTMax ,
    PCTAvg ,
    PCTMin ,
    AllAvg ,
    CASE WHEN AllMax > 79 THEN AllMax ELSE NULL END AS GreenUpper ,
    CASE WHEN AllMin > 79 THEN AllMin ELSE @GreenLower END AS GreenLower ,

    CASE WHEN AllMax < 79 THEN AllMax ELSE 
        CASE WHEN AllMax > 79 THEN @AmberUpper ELSE  NULL END 
    END AS AmberUpper ,
    @AmberLower AS AmberLower ,

    CASE WHEN AllMin > 59 THEN NULL ELSE @RedUpper END AS RedUpper ,
    CASE WHEN AllMin > 59 THEN NULL ELSE AllMin END AS RedLower

FROM    @Scores

最终这些数据将更加动态并提取实际值,但是现在我只是想让输出逻辑正确,这样我就可以将它插入图形组件并生成如下所示的图形: Whiskers chart

2 个答案:

答案 0 :(得分:1)

以下分两步完成工作:

  1. 将每个范围拆分为Upper&amp;较低的值,每个子范围一行。

  2. 取消隐藏子范围,以便在同一行显示每组。

  3. SELECT
      GroupedBy,
      PCTMax,
      PCTAvg,
      PCTMin,
      AllAvg,
      GreenUpper = MAX(CASE BandName WHEN 'Green' THEN Upper END),
      GreenLower = MAX(CASE BandName WHEN 'Green' THEN Lower END),
      AmberUpper = MAX(CASE BandName WHEN 'Amber' THEN Upper END),
      AmberLower = MAX(CASE BandName WHEN 'Amber' THEN Lower END),
      RedUpper   = MAX(CASE BandName WHEN 'Red'   THEN Upper END),
      RedLower   = MAX(CASE BandName WHEN 'Red'   THEN Lower END)
    FROM (
      SELECT
        s.GroupedBy,
        s.PCTMax,
        s.PCTAvg,
        s.PCTMin,
        s.AllAvg,
        b.BandName,
        Upper = CASE
          WHEN s.AllMax >= b.BandMin AND s.AllMin <= b.BandMax THEN
            CASE
              WHEN b.BandMax > s.AllMax THEN s.AllMax
              ELSE b.BandMax
            END
        END,
        Lower = CASE
          WHEN s.AllMax >= b.BandMin AND s.AllMin <= b.BandMax THEN
            CASE
              WHEN b.BandMin < s.AllMin THEN s.AllMin
              ELSE b.BandMin
            END
        END
      FROM Scores s
      CROSS JOIN (
        SELECT 'Green', 80, 2147483647 UNION ALL
        SELECT 'Amber', 60, 79         UNION ALL
        SELECT 'Red'  ,  0, 59
      ) b (BandName, BandMin, BandMax)
    ) s
    GROUP BY
      GroupedBy,
      PCTMax,
      PCTAvg,
      PCTMin,
      AllAvg
    

    subselect实现第一步,并使用辅助内联表来分割范围。外部选择使用分组来取消获取的值对。

    您可以使用此解决方案on SQL Fiddle,我在Scores表格中添加了更多边缘案例,以便更好地说明拆分。

答案 1 :(得分:0)

试试这个:

SELECT  GroupedBy
      , AllMax
      , AllMin
      , CASE WHEN AllMax > 79 THEN AllMax
             ELSE NULL
        END AS GreenUpper
      , CASE WHEN AllMin > 79 THEN AllMin
             ELSE @GreenLower
        END AS GreenLower
      , CASE WHEN AllMax BETWEEN 61 AND 80 THEN AllMax
             WHEN AllMax > 79
                  AND AllMin < 80 THEN @AmberUpper
             ELSE NULL
        END AS AmberUpper
      , @AmberLower AS AmberLower
      , @RedUpper AS RedUpper
      , CASE WHEN AllMin > 59 THEN NULL
             ELSE AllMin
        END AS RedLower
FROM    @Scores