如何根据字符串的一部分在SQL中进行聚合

时间:2019-07-08 18:54:40

标签: sql sql-server tsql split

我在表格中的一行看起来像这样

    Time                        TenantID  CallingService     PolicyList  PolicyInstanceList 
    2019-11-23 07:30:30.0000000 ########  S1                 p1, p2      pi1,pi2,pi3,pi4
    2019-11-23 07:30:31.0000000 ########  S1                 p1, p2      pi1,pi2,pi3,pi4
    2019-11-23 07:30:32.0000000 ########  S1                 p1, p2      pi1,pi2,pi3,pi4    
    2019-11-23 07:30:33.0000000 ########  S1                 p1, p2      pi1,pi2,pi3,pi4    
    2019-11-23 07:30:34.0000000 ########  S1                 p1, p2      pi1,pi2,pi3,pi4    
    2019-11-23 07:30:35.0000000 ########  S1                 p1, p2      pi1,pi2,pi3,pi4    
    2019-11-23 07:30:36.0000000 ########  S1                 p1, p2      pi1,pi2,pi3,pi4    
    2019-11-23 07:30:37.0000000 ########  S1                 p1, p2      pi1,pi2,pi3,pi4
    2019-11-23 07:30:38.0000000 ########  S1                 p1, p2      pi1,pi2,pi3,pi4           

我已经根据TenantID进行了汇总,因此看起来像这样

Time                        TADCount    TenantID
2019-11-23 00:00:00.0000    8           ########

但是,我需要为聚合添加更多的粒度,以便可以基于多个键来做到这一点。例如,

Time                        TADCount    TenantID  CallingService  PolicyList  PolicyInstanceList 
2019-11-23 00:00:00.0000    1           ########  S1              p2          pi3

这是我用于参考以实现第二代码块的聚合语句。

  SELECT DATEADD(DAY, DATEDIFF(DAY, 0, [Time]), 0) AS Time
      ,Count([TenantId]) AS TADCount, [TenantId]
      --,Count([PolicyList]) AS PolicyListCount, [PolicyList]
  FROM [dbo].[acms_data] 
  GROUP by DATEADD(DAY, DATEDIFF(DAY, 0, [Time]), 0),[TenantId] 

2 个答案:

答案 0 :(得分:1)

SELECT DATEADD(DAY, DATEDIFF(DAY, 0, [Time]), 0) AS Time
      , Count([TenantId]) AS TADCount
      , [TenantId]
      , CallingService
      , right(PolicyList,2) as PolicyList
      , substring(PolicyInstanceList, 9, 3) as PolicyInstanceList
  FROM [dbo].[acms_data] 
  GROUP BY DATEADD(DAY, DATEDIFF(DAY, 0, [Time]), 0)
         , [TenantId]
         , CallingService
         , right(PolicyList,2)
         , substring(PolicyInstanceList, 9, 3);

答案 1 :(得分:1)

如果您使用的是SQL Server 2016或更高版本,则可以访问string_split表值函数。在下面的示例中,我将其应用于policyList,而不是policyInstanceList,但是您可以根据需要更改逻辑。

select      time = ap.day,
            acms.tenantId,
            policyList = ltrim(sp.value),
            policyListCount = count(policyList)
from        acms_data acms
cross apply string_split(acms.policyList, ',') sp
cross apply (select day = convert(date, acms.time)) ap
group by    ap.day, acms.tenantId, sp.value

如果您的版本低于2016,则必须构建自己的字符串拆分函数。关于堆栈溢出,有很多关于创建自己的函数的问题。有关示例,请参见here

但是,一旦发现自己将csv列表存储在列中,则表明表开始非规范化。因此,如果您可以重组某些表,以便在另一个表中捕获Tennant和policyList(或policyInstanceList)之间的关系,那么将是比较理想的。