2012-04-20 79 views
2

我有一个简单的查询。类似这样的:TSQL GROUP BY部分字符串

SELECT l.list_name, COUNT(order_id) 
FROM orders o JOIN lists l ON l.order_id=o.order_id 
    WHERE l.list_name LIKE 'orders_1%' or l.list_name LIKE 'orders_2%' 
GROUP BY l.list_name 

情况如下:overight存储过程正在更新列表表,但如果有超过1000个订单,它会在部分中排列列表。

如果我有1200条订单,其中包含条件或列表'orders_1',那么我的程序将创建两个列表:'orders_1_1'和orders_1_2',第一个列表包含1,000和200个订单。

所以,当我跑我的查询来计算这些订单我会得到像这样的结果:

list_name     count 

orders_1     100 
orders_1_more_than_100_1 1000  
orders_1_more_than_100_2 200 
orders_2     400 
orders_3_1     1000  
orders_3_2     1000 
orders_3_3     420 
orders_3_more_than_100_1 1000  
orders_3_more_than_100_2 900 
orders_3_more_than_200_1 1000  
orders_3_more_than_200_2 1000 
orders_3_more_than_200_3 100  
orders_4     200 
orders_4_more_than_300  200 

我想获得应该是这样的结果:

list_name     count 

orders_1     100 
orders_1_more_than_100  1200  
orders_2     400 
orders_3     2420 
orders_3_more_than_100  1900 
orders_3_more_than_200  2100  
orders_4     200 
orders_4_more_than_300  200 

因此,它将总结所有开始相同的列表。

有关于此的任何想法? :)

这些是我在我的list_names列中的精确值:

WYS_AUT_PISMO_NR_6 
WYS_AUT_PISMO_NR_5_POWYZEJ_240 
WYS_AUT_PISMO_NR_5_DO_240 
WYS_AUT_PISMO_NR_4_POWYZEJ_240_5 
WYS_AUT_PISMO_NR_4_POWYZEJ_240_4 
WYS_AUT_PISMO_NR_4_POWYZEJ_240_3 
WYS_AUT_PISMO_NR_4_POWYZEJ_240_2 
WYS_AUT_PISMO_NR_4_POWYZEJ_240_1 
WYS_AUT_PISMO_NR_4_DO_240 
WYS_AUT_PISMO_NR_3_POWYZEJ_240 
WYS_AUT_PISMO_NR_3_DO_240 
WYS_AUT_PISMO_NR_2_POWYZEJ_240 
WYS_AUT_PISMO_NR_2_DO_240 
WYS_AUT_PISMO_NR_1 

我想要的是将它们分组,像这样:

WYS_AUT_PISMO_NR_6 
WYS_AUT_PISMO_NR_5_POWYZEJ_240 
WYS_AUT_PISMO_NR_5_DO_240 
WYS_AUT_PISMO_NR_4_POWYZEJ_240 /*fere I must group those 5 lists*/ 
WYS_AUT_PISMO_NR_4_DO_240 
WYS_AUT_PISMO_NR_3_POWYZEJ_240 
WYS_AUT_PISMO_NR_3_DO_240 
WYS_AUT_PISMO_NR_2_POWYZEJ_240 
WYS_AUT_PISMO_NR_2_DO_240 
WYS_AUT_PISMO_NR_1 

回答

1

这monstruous表达将隔离柱从参数的开头开始持续_如果有一个以上的强调:

select case when len (l.list_name) - len (replace (l.list_name, '_', '')) > 1 
      then left(l.list_name, 
         len (l.list_name) - charindex('_', reverse(l.list_name))) 
      else l.list_name 
     end 

或者,您可以从字符串中去掉'orders_',用点替换下划线并将其转换为浮点数,然后转换为int以删除小数,然后返回到使用此怪物的字符串:

select 'orders_' + cast (cast (cast (
     replace (substring (@str, 8, 100), '_', '.') 
     as float) as int) as varchar(100)) 

为了避免再次发生这类斑点,使用派生表,而不是lists

SELECT l.TrimmedListName, COUNT(order_id) 
FROM orders o 
JOIN 
(
    select lists.*, 
     -- Remove optional list continuation number 
      case when len (list_name) - len (replace (list_name, '_', '')) > 1 
       then left(list_name, 
          len (list_name) - charindex('_', reverse(list_name))) 
       else list_name 
      end AS TrimmedListName 
    from lists 
) l ON l.order_id=o.order_id 
WHERE (l.list_name LIKE 'orders_1%' or l.list_name LIKE 'orders_2%') 
GROUP BY l.TrimmedListName 
+0

你每天都会惊喜于我。只要看你的代码就可以显示你的技能。你太棒了!我会立即尝试:) – Misiu 2012-04-20 08:40:57

+0

有一个单一的问题。如果我有2个列表,可以这样说:orders_1_more_than_100_1 anf orders_1_more_than_100_2您的脚本工作正常,但如果我只有一个列表:orders_4,它会剪掉最后2个标记。 – Misiu 2012-04-20 08:57:42

+0

@Misiu我一定误解了一些东西,因为对我来说它留下了'orders_4'。你能否发布list_name列的确切值? – 2012-04-20 09:03:07

2

尝试像

select substring(l.list_name, 0, 8), count(order_Id) 
    FROM orders o JOIN lists l ON l.order_id=o.order_id 
    WHERE l.list_name LIKE 'orders_1%' or l.list_name LIKE 'orders_2%'   
    group by substring(l.list_name, 0, 8) 

已更新的问题的更新回答:

 select newColName, COUNT(order_id) 
    from 
    (
      select case when GetSubstringCount(l.list_name, '_', '') > 1 then 
     SUBSTRING(l.list_name, 0, len(l.list_name) - 2) 
     else l.list_name end as NewColName 
     , order_Id 
      FROM orders o JOIN lists l ON l.order_id=o.order_id  
      WHERE l.list_name LIKE 'orders_1%' or l.list_name LIKE 'orders_2%'   
    ) mySubTable 
    group by newColName 

你需要像This创建GetSubstringCount方法

+0

我不知道,我可以通过组串:)我会检查它的时候了:) – Misiu 2012-04-20 08:04:41

+0

多了一个编辑。如果我的列表名称长度不同,该怎么办?我会编辑我的问题 – Misiu 2012-04-20 08:06:19

+0

当然,没问题,尽管我想你只需要将该子字符串表达式放大一点,也许在字符串中找到第一个下划线,然后取一个下划线位置的长度+1 – 2012-04-20 08:08:17