【问题标题】:Group columns that don't exactly match in sql server对 sql server 中不完全匹配的列进行分组
【发布时间】:2019-10-17 15:27:50
【问题描述】:

我正在处理一个查询,以提取商家列表并获取该商家的交易计数。这是一个示例(注意:我的表格有更多列用于描述、位置、状态、金额、日期等,但这些是重要的)。

TransactionID    MerchantName            

1                MERCHANTA #123          
2                MERCHANTA #541          
3                MERCHANTA #456          
4                MERCHANTB #123          
5                MERCHANTB          
6                SOME MERCHANTC #123     

现在,我想将这些商家组合在一起,但由于每个商家可能拥有多个商店,因此他们的商家名称并不总是与其他交易相同。

我知道将它们组合在一起的唯一方法是以下标准查询,但它永远不会适用于不同的商店编号。

SELECT MerchantName, COUNT(*)
FROM Transactions
GROUP BY MerchantName

我的目标是使用正则表达式将商店编号替换为通配符或空白字符串,这样我就可以按商家将它们分组在一起,而不管商店编号如何。这是我的模式:[#*]\s?[a-zA-Z\d]?

预期输出:

MerchantName        TransactionCount          

MERCHANTA           3
MERCHANTB           2
SOME MERCHANTC      1

这甚至可能吗?如果是这样,这样做的好方法是什么?提前致谢。

【问题讨论】:

    标签: sql sql-server regex


    【解决方案1】:

    只是另一种选择。

    不需要 IIF() 或 CASE。我们只是在 charindex() 中添加一个“故障安全”

    示例

    Declare @YourTable Table ([TransactionID] int,[MerchantName] varchar(50))
    Insert Into @YourTable Values 
     (1,'MERCHANTA #123')
    ,(2,'MERCHANTA #541')
    ,(3,'MERCHANTA#456')     -- << made ugly
    ,(4,'   MERCHANTB #123') -- << made ugly
    ,(5,'MERCHANTB')
    ,(6,'SOME MERCHANTC #123')
    
    Select [MerchantName]
          ,TransCount    = count(*)
     From ( 
            Select [MerchantName] = ltriM(rtrim(left([MerchantName],charindex('#',[MerchantName]+'#')-1)))
             From  @YourTable
          ) A 
     Group By [MerchantName]
    

    退货

    MerchantName    TransCount
    MERCHANTA       3
    MERCHANTB       2
    SOME MERCHANTC  1
    

    > 编辑 *

    ...
    Select [MerchantName] = ltriM(rtrim(left([MerchantName],charindex('#',replace([MerchantName],'*','#')+'#')-1)))
     From  @YourTable
    ...
    

    【讨论】:

    • 这个解决方案对我有用。我需要使用它来解释星号*,但这可以满足我的需要。谢谢!
    • 我认为添加“故障安全”很巧妙。就个人而言,直到我看到你这样做,我才想到这一点。谢谢!
    • @QuestionGuyBob 谢谢你的笑容。我们都站在巨人的肩膀上。
    • @dvo 总是乐于提供帮助,关于 *,您可以在 charindex 部分用 # 替换 *
    • @JohnCappelletti 我将需要使用它,这样我就可以在一个声明中做到这两点。由于一些商家的店铺名称为MERCH *123,而其他商家的店铺名称为MERCH #123
    【解决方案2】:

    考虑:

    with cte as (
        select 
            TransactionID,
            iif(
                charindex(' #', MerchantName) > 0, 
                left(MerchantName, charindex(' #', MerchantName) - 1),
                MerchantName
            ) MerchantName
        from mytable
    )
    select MerchantName, count(*) TransactionCount
    from cte
    group by MerchantName
    

    在公用表表达式中,我们通过删除' #'(一个空格,然后是井号)之后的所有内容来修改商家名称。那么剩下要做的就是聚合。

    Demo on DB Fiddle

    商户名 |事务计数 :------------- | ---------------: 商人 | 3 商户 | 2 一些商家 | 1

    注意:这里假定' #' 始终代表拆分模式。

    【讨论】:

    • GMB 击败了我 - 这是我推荐假设始终存在“#”的方法,主要区别因素是示例数据演示。如果不存在,您可能还需要包含一些 RTRIM/LTRIM 函数。
    • 很好的解决方案。此数据库需要更新(仍在 sql server 2008 版本上),因此尚不支持。
    【解决方案3】:

    使用 stuffPatindex

    DECLARE @MYTAB AS TABLE(transactionId int IDENTITY(1,1),MerchantName nvarchar(50))
    
        insert into @MYTAB(MerchantName) values('MERCHANTA #123')
        insert into @MYTAB(MerchantName) values('MERCHANTA #541')          
        insert into @MYTAB(MerchantName) values('MERCHANTA #456')          
        insert into @MYTAB(MerchantName) values('MERCHANTB #123')         
        insert into @MYTAB(MerchantName) values('MERCHANTB')         
        insert into @MYTAB(MerchantName) values('SOME MERCHANTC #123')
    
        ;with cte as(
        select 
        case
        when stuff(MerchantName,patindex('%#%',MerchantName),4,'') is not null then 
        stuff(MerchantName,patindex('%#%',MerchantName),4,'') else MerchantName end [customer] from @MYTAB )
        select [customer],count(1) transactionCount from cte group by [customer]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-24
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多