Sql 2000 中行转列的查询方法

    发现问题

先建立一张准备查询的报表。

CREATE TABLE [TempTable]

(

    [Id]                INT IDENTITY(1,1) NOT NULL,

    -- 分为1 2 3 4 5 种类型

    [Type]                INT NOT NULL,

    -- 纪录不同类型的操作备注

    [Note]                NVARCHAR(100) NULL,

    -- 增加的时间

    [AddDateTime]        DATETIME NULL,

    

    CONSTRAINT [PK_TempTable_Id] PRIMARY KEY CLUSTERED

    (

        [Id] ASC

    ) WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]

) ON [PRIMARY]

    然后往里面插入一些临时的数据(插入时,预留一些类型是没有数据的)。

    INSERT INTO [TempTable]

VALUES(1,'操作',GETDATE())

INSERT INTO [TempTable]

VALUES(1,'操作',GETDATE())

INSERT INTO [TempTable]

VALUES(1,'操作',GETDATE())

INSERT INTO [TempTable]

VALUES(1,'操作',GETDATE())

    

INSERT INTO [TempTable]

VALUES(3,'操作',GETDATE())

INSERT INTO [TempTable]

VALUES(3,'操作',GETDATE())

INSERT INTO [TempTable]

VALUES(3,'操作',GETDATE())    

    现在我们要这样来统计数据,

    

日期

类型1

类型2

类型3

类型4

类型5

小计

2007-8-8

4

0

3

0

0

6

       
       

 

    如果拿到这样的结果,一开始会想到使用连接查询来查数据。

SELECT COUNT(1) AS [1] FROM [dbo].[TempTable] WHERE [Type] = 1 GROUP BY [Type]

 

    这样先查询出一个类型的数据,之后再组合起来。

 

SELECT

    [1].[1],

    [2].[2],

    [3].[3],

    [4].[4],

    [5].[5]

FROM

(SELECT COUNT(1) AS [1] FROM [dbo].[TempTable] WHERE [Type] = 1 GROUP BY [Type]) AS [1]

,

(SELECT COUNT(1) AS [2] FROM [dbo].[TempTable] WHERE [Type] = 2 GROUP BY [Type]) AS [2]

,

(SELECT COUNT(1) AS [3] FROM [dbo].[TempTable] WHERE [Type] = 3 GROUP BY [Type]) AS [3]

,

(SELECT COUNT(1) AS [4] FROM [dbo].[TempTable] WHERE [Type] = 4 GROUP BY [Type]) AS [4]

,

(SELECT COUNT(1) AS [5] FROM [dbo].[TempTable] WHERE [Type] = 5 GROUP BY [Type]) AS [5]

 

    以为这样大功告成了,可是查询出来的结果却发现没有值,这是因为有的类型里面是没有数据的(开始预插入数据也就是为了这点)。

    为什么没有数据显示呢?

    在Sql中如果我们Count(*)一个数据表一般是有数据返回的,没有数据则为0,不过如果我们在查询语句后面加了Group By 的话,那么查询条件的值没有数据,那么分组就不会返回任何数据。

    这样就导致了上面最原始的方式来进行行转列的方式失效了。

    

问题可以解决了吗?

    仔细想想,其实就是没有数据的时候,就不能返回值,那么只需要在没有值的情况下,我们自己加一个NULL值进去不就好了吗,于是可以把没有值的类型这样来写:

SELECT

    COUNT(*) - 1

FROM

(

    SELECT

        [Type]

    FROM

        [TempTable]

    WHERE

        [Type] = 2

    UNION ALL

        SELECT NULL

) AS [Temp]

WHERE

    [Type] IS NULL

GROUP BY

    [Type]

这样查询出来的结果就可以为 0 了,不过问题又出现了,那我怎么能知道这个类型什么时候有数据,什么时候又没呢?那样不是需要写IF判断了吗?这样就不是一个单独的SELECT语句能办到的事情了。

寻找突破口

    其实要有一个高效率的查询,还是做子查询的效率高,既然是按Type来进行查询,对它进行分组,那么我们可以把Type提出来作为一个类型表,然后根据这个类型表与此表做子查询,马上就可以得出结果。

    首先创建一个Type表

CREATE TABLE [TempTableType]

(

    [Id]                INT IDENTITY(1,1) NOT NULL,

    -- 分为1 2 3 4 5 种类型

    [TypeName]            NVARCHAR(10) NOT NULL

    

    CONSTRAINT [PK_TempTableType_Id] PRIMARY KEY CLUSTERED

    (

        [Id] ASC

    ) WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]

) ON [PRIMARY]

    插入类型数据:

    INSERT INTO [TempTableType]

VALUES('1')

INSERT INTO [TempTableType]

VALUES('2')

INSERT INTO [TempTableType]

VALUES('3')

INSERT INTO [TempTableType]

VALUES('4')

INSERT INTO [TempTableType]

VALUES('5')

    然后通过下面的语句就可以查出来对应类型的数量总计:

SELECT

    [TypeName],

    (

        SELECT COUNT(*) FROM [TempTable] WHERE [TypeName] = [Type]

    ) AS [Sum]

FROM

    [TempTableType]

    

TypeName

Sum

1

4

2

0

3

3

4

0

5

0

    然后结果 0 是不是就出来了,然后再来进行转列,就可以得到结果了。

最后的解决办法

    上面的解决办法,会动用的到另外的一张表,明显的不会是一个完美的解决方案,继续一步步分析,首先我们先获取有类型的数据总计:

    SELECT

        [Type],

        COUNT(1) AS [Sum]

    FROM

        [TempTable]

    GROUP BY

        [Type]

    然后会得到:

Type

Sum

1

4

3

3

    如果现在要把Type = 1的时候换成列怎么显示呢?使用最开始的那种连接查询方式?这显然已经不能行的,那么还有什么方式么?对了,可以使用 CASE 分支语句:

    SELECT

    ISNULL(SUM(CASE [Type] WHEN 1 THEN [Sum] END), 0)

FROM

(

    SELECT

        [Type],

        COUNT(1) AS [Sum]

    FROM

        [TempTable]

    GROUP BY

        [Type]

)AS [Temp]

    OK 这样可以显示出 Type =1 时的结果了,因为Type=1的只有一个,其余的都会为0,这样通过Sum来计算,也等于说只把多条纪录汇总为一条,就达到了显示的结果。同理的情况我们把剩下的类型写出来:

 

SELECT

    ISNULL(SUM(CASE [Type] WHEN 1 THEN [Sum] END), 0) AS [Type1],

    ISNULL(SUM(CASE [Type] WHEN 2 THEN [Sum] END), 0) AS [Type2],

    ISNULL(SUM(CASE [Type] WHEN 3 THEN [Sum] END), 0) AS [Type3],

    ISNULL(SUM(CASE [Type] WHEN 4 THEN [Sum] END), 0) AS [Type4],

    ISNULL(SUM(CASE [Type] WHEN 5 THEN [Sum] END), 0) AS [Type5]

FROM

(

    SELECT

        [Type],

        COUNT(1) AS [Sum]

    FROM

        [TempTable]

    GROUP BY

        [Type]

)AS [Temp]

Type1

Type2

Type3

Type4

Type5

4

0

3

0

0

    OK,我们的查询目的达到了,CASE语句能达到这样的效果是因为它能把未能查到的条件赋值为NULL所以根据这点,就可以解决分组后Count(*)无返回值的问题。

    有什么更好的方法多多交流。

转载于:https://www.cnblogs.com/sherrys/archive/2007/08/08/848124.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值