【问题标题】:How to group only by month and year?如何仅按月和年分组?
【发布时间】:2017-03-02 04:19:48
【问题描述】:

我对 SQL 有点熟悉。我使用 SQL Server 2012。

我有这张桌子:

|Id  | SiteId|    SiteDesc |IsNormal|     DateReview           |FrequencyId|
|3379|      5|     colon   |    1   |   2016-09-10 00:00:00.000|    1      |    
|3381|      5|     colon   |    0   |   2016-09-15 00:00:00.000|    1      |    
|3382|      5|     colon   |    1   |   2016-09-21 00:00:00.000|    1      |

|3489|      5|     colon   |    0   |   2016-08-10 00:00:00.000|    1      |    
|3851|      5|     colon   |    1   |   2016-08-16 00:00:00.000|    1      |

|3537|      2|     dogon   |    1  |    2016-05-05 00:00:00.000|    1      |    
|3863|      2|     dogon   |    1  |    2016-05-20 00:00:00.000|    1      |    

IsNormal 列属于BIT 数据类型。

我需要按SiteIdDateReview 对表格进行分组(只有月份和年份)。如果在IsNormal 列中至少一行的属性为假,则在分组表中它必须为假。

这是所需的分组表:

 | SiteId|    SiteDesc |IsNormal|     DateReview           |FrequencyId|
 |      5|     colon   |    0   |   2016-09-10 00:00:00.000|    1      |        
 |      5|     colon   |    0   |   2016-08-10 00:00:00.000|    1      |    
 |      2|     dogon   |    1   |   2016-05-05 00:00:00.000|    1      |    

【问题讨论】:

  • @gaurav 选择中带有分组依据的任何项目都必须在分组依据或聚合中:不符合此规则。

标签: sql sql-server tsql sql-server-2012 group-by


【解决方案1】:

我用过这段代码,你也可以试试。

 select  CAST(MONTH(SalesDate) AS VARCHAR(2)) + '-' + CAST(YEAR(SalesDate) AS VARCHAR(4)),  sum(TSalesAmt) as 'GrandTotal' from CreditSales group by  CAST(MONTH(SalesDate) AS VARCHAR(2)) + '-' + CAST(YEAR(SalesDate) AS VARCHAR(4))

【讨论】:

    【解决方案2】:

    使用year()month()

    select SiteId, min(SiteDesc) as SiteDesc,
           min(case when IsNormal = 0 then 0 else 1 end) as IsNormal,
           min(DateReview) as DateReview,
           min(FrequencyId) as FrequencyId
    from t
    group by SiteId, year(DateReview), month(DateReview)
    order by min(DateReview) desc;
    

    这只是使用年份和月份进行聚合。然后它使用聚合函数提取列值。对于DateReview,相应的函数似乎是min()

    【讨论】:

      【解决方案3】:

      SQL Server 无法按原样聚合bit 列,因此先将其转换为int,然后使用MIN,然后再将其转换回bit

      要按月分组,我使用以下公式:

      DATEADD(month, DATEDIFF(month, '20010101', DateReview), '20010101')
      

      您可以选择任何锚定日期而不是“20010101”,它可以是该月的任何第一天。这个想法很简单。 DATEDIFF(month,...) 计算锚定日期与表中的值之间的月数。这是整数 - 跨越月份边界的次数。然后将此数字添加回锚定日期。此表达式的结果是DateReview 的值被截断为当月的第一天。

      查询

      SELECT
          SiteId
          ,MIN(SiteDesc) AS SiteDesc
          ,CAST(MIN(CAST(IsNormal AS int)) AS bit) AS IsNormal
          ,MIN(DateReview) AS DateReview
          ,MIN(FrequencyId) AS FrequencyId
      FROM T
      GROUP BY
          SiteId
          ,DATEADD(month, DATEDIFF(month, '20010101', DateReview), '20010101')
      

      【讨论】:

      • 只是好奇为什么不GROUP BY YEAR(DateReview), MONTH(DateReview)
      • @Eric,在这种情况下没有区别。 DATEDIFF 的公式更通用。您可以将week/quarter/hour/etc 代替month 以其他间隔分组。
      猜你喜欢
      • 2021-03-10
      • 2012-12-10
      • 1970-01-01
      • 1970-01-01
      • 2011-07-21
      • 2021-10-16
      • 1970-01-01
      相关资源
      最近更新 更多