【问题标题】:SQL Group By Customized Categories (Number)SQL 按自定义类别分组(数量)
【发布时间】:2017-03-08 13:51:42
【问题描述】:

我在编写一个查询时遇到了一些问题。

我有一个由文件及其大小(以字节为单位)组成的表。它看起来像这样:

FileUrl | FileSize
------------------
xyz.docx | 2794496
qwe.ppt | 655360
asd.pdf | 1388782
...
...

我想要的是根据我将定义的不同大小组来查找文件数、占总文件数的百分比和占总文件大小的百分比。所以应该是这样的:

Size Category | Number of Files | % of Total File Count | ½ of Total File Size
------------------------------------------------------------------------------
0-1 MB        | 235             | 80%                   | 20%
1-10 MB       | 57              | 20%                   | 80%
10-50 MB
...
...

创建此类组然后找到这些百分比的最佳方法是什么?我想不出解决方案,而且我的在线搜索也没有任何帮助。

提前谢谢你

【问题讨论】:

标签: sql sql-server reporting-services


【解决方案1】:

这是使用apply 和窗口函数的一种方法:

select v.sizecategory, count(*) as numfiles,
       (count(*) / sum(1.0 * count(*)) over () as ratio_files,
       (sum(filesize) / sum(sum(filesize) * 1.0)) over () as ratio_sizes
from t outer apply
     (values (case when t.filesize < 1000000 then '0-1 MByte'
                   when t.filesize < 10000000 then '1-10 MByte'
                   when t.filesize < 50000000 then '10-50 MByte'
                   . . .
              end)
     ) v(sizecategory) 
group by v.sizecategory
order by min(t.filesize);

【讨论】:

    【解决方案2】:

    用例和 CTE

    with CTE as
    (
    select case 
               when filesize < 1024 then '0 - 1 MB'
               when ...
               else '50MB+'
           end as FileGroup,
           Filedata.*
    from Filedata
    )
    select FileGroup, 
           count(Filename) as NumberOfFiles, 
           count(filename) / (select count(*) from CTE) as PCTotalCount, 
           sum(Filesize) / (select sum(filesize) from CTE) as PCTotalSize
    from CTE
    group by FileGroup
    

    【讨论】:

      【解决方案3】:

      您要的是直方图。这可能会有所帮助:

      SELECT FLOOR((filesize*1000000)/10.00)*10 As SizeCategory, 
             COUNT(*) AS [NumFiles]
      FROM TableName
      GROUP BY FLOOR((filesize*1000000)/10.00)*10 
      ORDER BY 1
      

      这将为您提供大小相等的间隔。

      【讨论】:

      • 要格式化为code,选择文本并按ctrl-k或在每行前添加4个空格
      • 谢谢!就这么做了。
      【解决方案4】:

      使用如下范围创建您的组表:

      RangeLow | RangeHigh | Number of Files | PercentCount | ½ of Total 
      ------------------------------------------------------------------------------
          0    |  1024000  | 235             | 80%                   | 20%
      1024000  |  2048000  | 57              | 20%                   | 80%
      

      那么您的查询可能如下所示:

      Select FileUrl, FileSize, (Select PercentCount  From GroupTable Where FileSize >= RangeLow AND FileSize < RangeHigh )  From FilesTable 
      

      【讨论】:

      • 其中一个范围应该使用&lt;&gt;,否则你可以获得两个范围内的文件。
      【解决方案5】:

      如果您无法调整数据集 SQL,则可以改用 SSRS 报告中的表达式对文件大小进行分类。在行标题单元格和行组的 Group on 表达式中使用如下表达式:

      =Switch(Fields!FILESIZE.Value < 1024, "0-1 MB",
      Fields!FILESIZE.Value < 10240, "1-10 MB",
      Fields!FILESIZE.Value < 51200, "10-50 MB",
      True, "50+ MB")
      

      然后您也可以计算报告中的总数。使用Count()Sum函数的第二个参数来定义作用域:

      =Count(Fields!FILESIZE.Value)
      =Count(Fields!FILESIZE.Value, "RowGroup") / Count(Fields!FILESIZE.Value, "DataSet1")
      =Sum(Fields!FILESIZE.Value, "RowGroup") / Sum(Fields!FILESIZE.Value, "DataSet1")
      

      【讨论】:

        【解决方案6】:

        或者你可以这样做:

        SELECT
        CASE 
        WHEN FileSize < 1024 THEN '0-1 MB'
        WHEN FileSize  FileSize < 10240 THEN '1-10 MB'
        WHEN FileSize  FileSize < 51200 THEN '10-50 MB'
        -- continue with this...
        END 'SizeCategory',
        count (fileUrl) as 'Number of Files',
        (count (fileUrl)) / (sum(count (fileUrl)) over (order by null)) as '% of Total File Count',
        (sum(FileSize)) / (sum(FileSize) over (order by null)) as '½ of Total File Size'
        FROM table
        GROUP BY SizeCategory
        

        【讨论】:

        • 使用 case 时,按顺序计算。因此,您不需要FileSize &gt;= 1024,只需要Filesize &lt; 10240(对每种情况重复)。您的最终选择是Else,这将是最大范围
        • 这完全有道理。感谢您的评论:)
        【解决方案7】:

        这里有许多完全有效的答案。 然而,我更喜欢维护一个通用的Tier Table,它可以服务于多个master,并从代码中删除逻辑并提供更多的灵活性。 p>

        示例

        Declare @Tier table (Tier_Grp varchar(50),Tier_Seq int,Tier_Dsc varchar(100),Tier_R1 float,Tier_R2 float)
        Insert Into @Tier values
        ('File Size',1  ,'0-1 MB'   ,0    ,1e+6 ),
        ('File Size',2  ,'1-10 MB'  ,1e+6 ,1e+7 ),
        ('File Size',3  ,'10-50 MB' ,1e+7 ,5e+7 ),
        ('File Size',4  ,'50-100 MB',5e+7 ,1e+8 ),
        ('File Size',5  ,'100 MB +' ,1e+8 ,9e+11 ),
        ('File Size',999,'Total'    ,0    ,9e+12 )  --< Optional
        
        Declare @YourTable table (FileUrl varchar(50),FileSize int)
        Insert Into @YourTable values
        ('xyz.docx',2794496),
        ('qwe.ppt',655360),
        ('asd.pdf',1388782)
        
        ;with cte as (
            Select A.* 
                  ,Cnt   = count(FileSize)+0.0
                  ,Total = isnull(sum(cast(FileSize as float)),0)
             From  @Tier A
             Left Join  @YourTable B on Tier_Grp='File Size' and B.FileSize >=Tier_R1 and B.FileSize<Tier_R2
             Group By Tier_Grp
                     ,Tier_Seq
                     ,Tier_Dsc
                     ,Tier_R1
                     ,Tier_R2
        )
        Select Tier_Grp
              ,Tier_Dsc
              ,[Number of Files]  = cast(Cnt as int)
              ,[Number of Bytes]  = Total 
              ,[Percent of Files] = format(Cnt/max(Cnt) over (),'0.0%')
              ,[Percent of Size]  = format(Total/max(Total) over (),'0.0%')
         From cte
         Order by Tier_Seq
        

        退货

        【讨论】:

          猜你喜欢
          • 2018-01-06
          • 2020-11-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多