摘要统计信息和相应日期 - SQL Server

时间:2014-04-11 22:15:06

标签: sql sql-server tsql

我希望有人可以提供帮助。这个问题最近提交给我,我认为这很容易,但(个人)认为这有点困难。我可以在Excel和SSRS中完成 - 但我很好奇我是否能够在SQL Server中完成...

我想为数据集创建一组摘要统计信息(Max,Min)。很容易......但我想将相应的日期与这些值相关联。

以下是我的数据:

Begin

我有年度数据(不完全 - 但除此之外)我使用一系列CASE WHEN语句生成这样的透视摘要。这很好 - 输出见于右侧(上图)。

每次输出这些数据时 - 我都想提供所有历史数据的摘要(为简洁起见,我只显示最新数据)。那么......问题是如何获取如下所示的输出(在不同的日期)并提供类似我右边的摘要数据集?

Summary

所以 - 一点背景。我已经设法使用UNION加入Min和Max值,这一点很好。棘手的一点(我认为)是如何形成一个INNER JOIN,使用子查询,Max或Min结果值为每个Type返回相应的Max或Min日期?现在我很有可能是一个白痴,并且遗漏了一些明显的东西....但是......真的很感激任何人的帮助......

非常感谢提前

2 个答案:

答案 0 :(得分:1)

如果您的SQLServer是2005或更高版本,可以使用PIVOT命令,但是数据透视表的原始数据需要采用特定格式,而我提出的查询是丑陋的

WITH minmax AS (
SELECT TYPE, RESULT, [date]
     , row_number() OVER (partition BY TYPE ORDER BY TYPE, RESULT) a
     , row_number() OVER (partition BY TYPE ORDER BY TYPE, RESULT DESC) d
FROM t)
SELECT info
     , cam = CASE charindex('date', info)
                  WHEN 0 THEN cast(cast(cam AS int) AS varchar(50))
                  ELSE cast(cam AS varchar(50))
             END
     , car = CASE charindex('date', info)
                  WHEN 0 THEN cast(cast(car AS int) AS varchar(50))
                  ELSE cast(cam AS varchar(50))
             END
     , cat = CASE charindex('date', info)
                  WHEN 0 THEN cast(cast(cat AS int) AS varchar(50))
                  ELSE cast(cam AS varchar(50))
             END
FROM (SELECT TYPE, 'maxres' info, RESULT value FROM minmax WHERE 1 = d
      UNION ALL
      SELECT TYPE, 'minres' info, RESULT value FROM minmax WHERE 1 = a
      UNION ALL
      SELECT TYPE, 'maxdate' info , [date] value FROM minmax WHERE 1 = d
      UNION ALL
      SELECT TYPE, 'mindate' info , [date] value FROM minmax WHERE 1 = a) DATA
     PIVOT
     (max(value) FOR TYPE IN ([CAM], [CAR], [CAT])) pvt

它只是一个概念证明所以SQLFiddle我使用了一组减少的假数据(每3类3行)

数据准备后

SELECT TYPE, 'maxres' info, RESULT value FROM minmax WHERE 1 = d
UNION ALL
SELECT TYPE, 'minres' info, RESULT value FROM minmax WHERE 1 = a
UNION ALL
SELECT TYPE, 'maxdate' info , [date] value FROM minmax WHERE 1 = d
UNION ALL
SELECT TYPE, 'mindate' info , [date] value FROM minmax WHERE 1 = a

value列被隐式地转换为更复杂的数据类型,在这种情况下是DateTime(在同一列中不能有不同的数据类型),以预期的方式查看数据需要显式转换,并且已完成

中的CASE和CAST
, cam = CASE charindex('date', info)
             WHEN 0 THEN cast(cast(cam AS int) AS varchar(50))
             ELSE cast(cam AS varchar(50))
        END

CASE检查数据类型,查找子字符串' date'在info列中,然后将行值转换回INT为minres和maxres列,并且在任何情况下将值转换为varchar(50)以再次具有相同的数据类型

<强>更新
使用sql_variant,不需要CASE CAST块,谢谢Ryx5

WITH minmax AS (
SELECT TYPE, RESULT, [date]
     , row_number() OVER (partition BY TYPE ORDER BY TYPE, RESULT) a
     , row_number() OVER (partition BY TYPE ORDER BY TYPE, RESULT DESC) d
FROM table_name)
SELECT info
     , [CAM], [CAR], [CAT]
FROM (SELECT TYPE, 'maxres' info, cast(RESULT as sql_variant) value 
      FROM minmax WHERE 1 = d
      UNION ALL
      SELECT TYPE, 'minres' info, cast(RESULT as sql_variant) value 
      FROM minmax WHERE 1 = a
      UNION ALL
      SELECT TYPE, 'maxdate' info , cast([date] as sql_variant) value 
      FROM minmax WHERE 1 = d
      UNION ALL
      SELECT TYPE, 'mindate' info , cast([date] as sql_variant) value 
      FROM minmax WHERE 1 = a) DATA
     PIVOT
     (max(value) FOR TYPE IN ([CAM], [CAR], [CAT])) pvt

答案 1 :(得分:1)

此查询将完成此任务,并适用于所有TYPE

SELECT 
    Description, [CAR], [CAT], [MAT], [EAT], [PAR], [MAR], [FAR], [MOT], [LOT], [COT], [ROT]
FROM 
    (SELECT 
        unpvt.TYPE
        ,unpvt.Description
        ,unpvt.value
     FROM (
        SELECT 
            t.TYPE
            ,CONVERT(sql_variant,MAX(maxResult.MAX_RESULT)) as MAX_RESULT
            ,CONVERT(sql_variant,MIN(minResult.MIN_RESULT)) as MIN_RESULT
            ,CONVERT(sql_variant,MAX(CASE WHEN maxResult.MAX_RESULT IS NOT NULL THEN t.DATE ELSE NULL END)) as MAX_DATE
            ,CONVERT(sql_variant,MIN(CASE WHEN minResult.MIN_RESULT IS NOT NULL THEN t.DATE ELSE NULL END)) as MIN_DATE
        FROM 
            table_name t -- You need to set your table name
            LEFT JOIN (SELECT 
                           TYPE
                           ,MIN(RESULT) as MIN_RESULT
                       FROM 
                           table_name -- You need to set your table name
                       GROUP BY
                           TYPE) minResult
                on minResult.TYPE = t.TYPE
                and minResult.MIN_RESULT = t.RESULT 
            LEFT JOIN (SELECT 
                           TYPE
                           ,MAX(RESULT) as MAX_RESULT
                       FROM 
                           table_name -- You need to set your table name
                       GROUP BY
                           TYPE) maxResult
                on maxResult.TYPE = t.TYPE
                and maxResult.MAX_RESULT = t.RESULT
        GROUP BY
            t.TYPE) U
    unpivot ( 
        value 
        for Description in (MAX_RESULT, MIN_RESULT, MAX_DATE, MIN_DATE)
            ) unpvt) P
PIVOT
(  
    MAX(value)
    FOR TYPE IN ([CAR], [CAT], [MAT], [EAT], [PAR], [MAR], [FAR], [MOT], [LOT], [COT], [ROT])
)AS PVT

DEMO: SQLFIDDLE

CONVERT(sql_variant,是针对公共数据类型的列的强制转换。当您使用子查询FROM运行时,这是UNPIVOT运算符的要求。