根据TSQL / Microsoft SQL Server

时间:2015-05-08 23:12:01

标签: sql sql-server-2008 tsql ms-access-2010

好的,这是我的示例数据表。 itemCode和dateType有一个唯一的键,因此没有itemCode可以重复dateType,反之亦然。 dateStatus也是一种数据类型。

+----+----------+----------+------------+-----------+--------------+
| id | itemCode | dateType | dateStatus |  dateDue  | dateComplete |
+----+----------+----------+------------+-----------+--------------+
|  1 |      501 | aa       |          1 | 1/1/2014  | 5/1/2014     |
|  2 |      501 | bb       |          0 | 1/2/2014  |              |
|  3 |      501 | cc       |          0 | 1/3/2014  |              |
|  4 |      602 | aa       |          0 | 1/4/2014  |              |
|  5 |      602 | bb       |          1 | 1/5/2014  | 5/5/2014     |
|  6 |      602 | cc       |          0 | 1/6/2014  |              |
|  7 |      602 | dd       |          0 | 1/7/2014  |              |
|  8 |      703 | bb       |          0 | 1/8/2014  |              |
|  9 |      703 | cc       |          0 | 1/9/2014  |              |
| 10 |      703 | dd       |          1 | 1/10/2014 | 5/10/2014    |
+----+----------+----------+------------+-----------+--------------+

我试图将dateType与itemCode相对应,并使其值为dateComplete或dateDue,具体取决于dateStatus是0还是1。

+----------+---------------+---------------+---------------+----------------+
| itemCode |      aa       |      bb       |      cc       |       dd       |
+----------+---------------+---------------+---------------+----------------+
|      501 | fin: 5/1/2014 | due: 1/2/2014 | due: 1/3/2014 |                |
|      602 | due: 1/4/2014 | fin: 5/5/2014 | due: 1/6/2014 | due: 1/7/2014  |
|      703 |               | due: 1/8/2014 | due: 1/9/2014 | fin: 5/10/2014 |
+----------+---------------+---------------+---------------+----------------+

我可以在Access Query CrossTab中轻松完成此操作,而SQL结果可以

TRANSFORM First(Switch([dateStatus]=0,"due: " & [dateDue],
                       [dateStatus]=1,"fin: " & [dateComplete])) AS Expr1
SELECT Table1.itemCode
FROM Table1
GROUP BY Table1.itemCode
PIVOT Table1.dateType In ("aa","bb","cc","dd");

但我无法弄清楚如何在TSQL / Microsoft SQL服务器管理工​​作室中构建此查询。我可以完成一些基本的支点,但是聚合函数似乎没有提取值,所以我认为查询可能是枢轴,连接和case语句的组合。或者也许我对复杂的事情感到困惑。

任何代码丢弃以供参考都会非常有帮助。感谢。

2 个答案:

答案 0 :(得分:1)

一种选择是使用条件聚合来pivot您的结果,但您还必须使用case来选择正确的日期:

select itemcode,
  max(case when dateType = 'aa' and dateStatus = 0 
           then 'due:' + cast(dateDue as varchar(20))
           when dateType = 'aa' and dateStatus = 1
           then 'fin:' + cast(dateComplete as varchar(20))
      end) as aa,
  max(case when dateType = 'bb' and dateStatus = 0 
           then 'due:' + cast(dateDue as varchar(20))
           when dateType = 'bb' and dateStatus = 1
           then 'fin:' + cast(dateComplete as varchar(20))
      end) as bb,
  max(case when dateType = 'cc' and dateStatus = 0 
           then 'due:' + cast(dateDue as varchar(20))
           when dateType = 'cc' and dateStatus = 1
           then 'fin:' + cast(dateComplete as varchar(20))
      end) as cc,
  max(case when dateType = 'dd' and dateStatus = 0 
           then 'due:' + cast(dateDue as varchar(20))
           when dateType = 'dd' and dateStatus = 1
           then 'fin:' + cast(dateComplete as varchar(20))
      end) as dd
from Table1
group by itemCode

另一种选择是使用pivot命令,但您仍然需要在子查询中使用case语句来创建包含日期的正确值。

答案 1 :(得分:1)

试一试。它比接受的答案稍微简单一些,它可以更加可扩展,比如说添加了另一个dateType。您所要做的就是在pivot中添加值,而不是整个新的case语句。

DECLARE @pivotCols VARCHAR(MAX);

SELECT @pivotCols =  COALESCE(@pivotCols + ',','') + QUOTENAME(dateType)
FROM @yourTable
GROUP BY dateType

EXEC
(
'SELECT *
FROM
(
    SELECT  itemCode,
            CASE 
                WHEN dateStatus = 1 
                    THEN ''fin: '' + CAST(dateComplete AS CHAR(10))
                ELSE ''due: ''  + CAST(dateDue AS CHAR(10))
            END dateDue,
            dateType
    FROM @yourTable
) A
PIVOT
(
    MAX(dateDue) FOR dateType IN (' + @pivotCols + ')
) pvt'
)