2012-04-20 94 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