zoukankan      html  css  js  c++  java
  • Sql 2000 中行转列的查询方法

     发现问题

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

    CREATE TABLE [TempTable] 
    (  
    [Id]  INT IDENTITY(1,1NOT NULL
        
    -- 分为1 2 3 4 5 种类型 
        [Type]   INT NOT NULL
        
    -- 纪录不同类型的操作备注 
        [Note]  NVARCHAR(100NULL
        
    -- 增加的时间 
        [AddDateTime]        DATETIME NULL
    )

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

    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,1NOT NULL
        
    -- 分为1 2 3 4 5 种类型 
        [TypeName] NVARCHAR(10NOT NULL 

     
          

        插入类型数据:   

    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(1AS [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(1AS [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), 0AS [Type1]

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

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

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

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

    FROM ( 

        
    SELECT [Type],COUNT(1AS [Sum] 

        
    FROM [TempTable] 

        
    GROUP BY [Type] 

    )
    AS [Temp] 

    Type1

    Type2

    Type3

    Type4

    Type5

    4

    0

    3

    0

    0

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

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

  • 相关阅读:
    关于putty使用详解
    ORA12505: TNS: 监听程序当前无法识别连接描述符中所给出的SID等错误解决方法
    VMware的“Bridge”、“NAT”、“Hostonly”上网方式的区别
    转贴一个很全的sql用法
    网站
    sql exsits问题!!
    petshop4.0 profile
    一些应该知道的
    继承System.Web.UI.Page的页面基类
    应用程序域(Application Domain)
  • 原文地址:https://www.cnblogs.com/symbol441/p/921172.html
Copyright © 2011-2022 走看看