SQL - 有命令这样做吗?

时间:2010-08-18 13:04:42

标签: sql sql-server-2005 crosstab

我有一张表,目前有很长的设备列表和有关何时售出的信息。我需要拿一张看起来像这样的表:

Item   |  Time Sold
--------------------
  A        05/2010
  B        04/2010
  C        03/2010
  A        04/2010
  A        05/2010

然后有一个表格,该项目作为第一列,日期的计数为列标题,如下所示:

Item   |   Count_03/2010   |  Count_04/2010  |  Count_05/2010
-------------------------------------------------------------
  A    |         0         |         1       |        2
  B    |         0         |         1       |        0
  C    |         1         |         0       |        0

有一种简单的方法吗?我知道在其他语言中有一个命令可以执行它,想知道SQL是否有一个。

修改

我的问题是有多个表,在某些表中,月份可能与其他表格不同。无论如何编写一个将适用于它们的脚本,通过获取列出的变量然后使用它们来创建代码中的列?如果我知道月份总是相同的话,我可以写一个,但由于它们是可变的,有没有办法做到这一点。

4 个答案:

答案 0 :(得分:4)

SQL Server 2005及更高版本有一个名为pivot的东西,但它仍然不是一个命令,你需要知道Time sold列中的值。你可以使用Itzik Ben-Gan在他的Inside Microsoft SQL Server 2008: T-SQL Querying书中所展示的动态透视方法

实施例

create table #test (Item char(1),  TimeSold varchar(20))

  insert #test values('A','05/2010')
  insert #test values('B','04/2010')
  insert #test values('C','03/2010')
  insert #test values('A','04/2010')
  insert #test values('A','05/2010')

  SELECT *
FROM
(SELECT Item,TimeSold
FROM #test) AS pivTemp
PIVOT
(   COUNT(TimeSold)
    FOR TimeSold IN ([05/2010],[04/2010],[03/2010])
) AS pivTable

答案 1 :(得分:3)

我没有测试过,但以下情况应该有效。我使用子查询来获得所需的结果:

select item, 
(select count(*) from items i where time_sold between '02/2010' AND '03/2010' i.item=item ),
(select count(*) from items i where time_sold between '03/2010' AND '04/2010' i.item=item ),
(select count(*) from items i where time_sold between '04/2010' AND '05/2010' i.item=item )
from items;

答案 2 :(得分:2)

本机MS-SQL不提供任何以您想要的表格格式显示数据的功能,而不知道您要从中生成列名的值。

有一个great article on dynamically creating crosstab queries in MS-SQL。这是一个黑客,但看起来它应该工作。

否则采取更灵活的方法......

Select Distinct
Item,
Time Sold,
Count([Item])
From
MyTable
Group By
Item,
Time Sold

这会给你:


    Item | Time Sold | Count
    ------------------------
    A    | 05/2010   | 2
    A    | 04/2010   | 1
    B    | 04/2010   | 1
    C    | 03/2010   | 1

这是一种更适合数据分析的格式,因为您可以编写查询来处理数据,因为列名已知。

例如,您可以在报告工具中使用此数据:

  • 计算所有已售商品
  • 显示明确的日期列表
  • 显示销售商品最多的日期列表

要使其符合您所要求的报告格式,您最好使用Crystal Reports或Excel等报告工具。

Excel和Crystal Report都支持数据透视表,用于以您请求的表格格式显示数据(而且它看起来也会更好!)。

答案 3 :(得分:1)

您可以group by获取每个项目的汇总结果。使用sumcase,您可以计算特定时期内的商品数量。例如:

select  item
,       sum(case when time_sold between '02/2010' and '03/2010' then 1 end)
,       sum(case when time_sold between '03/2010' and '04/2010' then 1 end)
,       sum(case when time_sold between '04/2010' and '05/2010' then 1 end)
from    items
group by
        item

如果您有多种格式的源表,请在子查询中将它们合并在一起。我将此示例限制为仅一个范围以节省空间:

select  item
,       sum(IsInRange1)
from    (
        select  item
        ,       case when time_sold between '01/2010' and '03/2010' 
                          then 1 end as IsInRange1
        from    usa_items
        union all
        select  item
        ,       case when time_sold in ('gennaio', 'febbraio', 'marzo') 
                          then 1 end
        from    italian_items
        union all
        select  item
        ,       case when time_sold between '2010-01-01' and '2010-03-01' 
                          then 1 end
        from    iso_items
        ) SubqueryAlias
group by
        item