我有一个包含列的Excel文件,
C_IP
SESSION_ID
CS_USER_AGENT
CS_URI_STEM
CS_URI_QUERY
WEB_LINK
由于Oracle(11g)中允许的字符串大小的限制,我无法聚合上述属性。我试图使用用户定义的聚合函数。我想聚合“WEB_LINK”列,并按C_IP进行分组。是否可以在Excel中执行此操作?
我尝试使用的SQL查询是,
CREATE TABLE WEBLOG_AGG AS
SELECT C_IP,
tab_to_string(CAST(COLLECT(WEB_LINK) AS T_VARCHAR2_TAB)) AS WEBLINKS
FROM WEBLOG_SESSION
GROUP BY C_IP;
答案 0 :(得分:3)
我想在clob
中连接比编写VBA代码更容易。
15:34:36 SYSTEM@dwal> create table t1 ( group_col number, value varchar2(1 byte) );
Table created.
Elapsed: 00:00:00.10
15:34:38 SYSTEM@dwal> insert into t1
15:35:34 2 select 1, decode(mod(rownum,5), 0,0,1) from dual connect by rownum <= 4001
15:36:20 3 union all
15:36:22 4 select 2, decode(mod(rownum,5), 0,0,1) from dual connect by rownum <= 4001
15:36:27 5 ;
8002 rows created.
Elapsed: 00:00:00.05
15:36:28 SYSTEM@dwal> commit;
Commit complete.
Elapsed: 00:00:00.02
15:36:31 SYSTEM@dwal> create type t_varchar2_tab is table of varchar2(1);
15:37:11 2 /
Type created.
Elapsed: 00:00:00.50
15:38:15 SYSTEM@dwal> ed
Wrote file S:\tools\buffer.sql
1 create function tab_to_str(tab in t_varchar2_tab) return clob
2 as
3 result clob;
4 begin
5 for i in tab.first .. tab.last loop
6 result := result || tab(i);
7 end loop;
8 return result;
9* end;
15:38:46 SYSTEM@dwal> /
Function created.
Elapsed: 00:00:00.19
15:46:01 SYSTEM@dwal> select group_col
15:46:04 2 ,length(tab_to_str(cast(collect(value) as t_varchar2_tab))) len
15:46:10 3 ,substr(tab_to_str(cast(collect(value) as t_varchar2_tab)), 1, 20) val
15:46:12 4 from t1 group by group_col;
GROUP_COL LEN VAL
---------- ------ --------------------
1 4001 11011110111101111011
2 4001 11011110111101111011
Elapsed: 00:00:01.13
答案 1 :(得分:2)
在我在这个问题中看到它之前,我甚至没有听说过COLLECT()
函数,但它看起来非常有用。基于我所阅读的内容,我认为以下内容应该在聚合web_link列时将Excel工作表缩减为唯一行。它不会动态执行(这可能是您正在寻找的)但是一旦数据存在就可以在整个工作表上运行它。
Public Type Entry
C_IP As String
rowNum As Integer
End Type
Public entryList() As Entry
Sub AggregateRows()
Dim lastRow As Integer
Dim i As Integer
Dim webLinks As String
Dim entryItem As Entry
Const C_IPColumn As Integer = 1 ' This is the column number of the C_IP column
Const WEB_LINKColumn As Integer = 6 ' This is the column number of the WEB_LINK column
ReDim entryList(0)
' Get the last used row on the sheet
lastRow = ActiveSheet.Cells.Find("*", SearchOrder:=xlByRows, LookIn:=xlValues, SearchDirection:=xlPrevious).Row
' Loop through all of the rows
For i = 1 To lastRow
' See if we've already encountered the C_IP in this row
entryItem = GetEntry(ActiveSheet.Cells(i, C_IPColumn).Value)
If Not entryItem.C_IP = "" Then
' We have, so add the current web link to the list for the row associated with this C_IP
webLinks = ActiveSheet.Cells(entryItem.rowNum, WEB_LINKColumn).Value
webLinks = webLinks & ", " & ActiveSheet.Cells(i, WEB_LINKColumn).Value
ActiveSheet.Cells(entryItem.rowNum, WEB_LINKColumn).Value = webLinks
' Now remove this row (since it has been grouped with row with the same C_IP)
ActiveSheet.Rows(i).Delete
' Decrement our counters by 1 since we have 1 fewer rows (assuming we're not on the last row already)
If Not i = lastRow Then
i = i - 1
lastRow = lastRow - 1
End If
Else
' We've not encountered this C_IP yet, so add it to the list
ReDim Preserve entryList(UBound(entryList) + 1)
entryList(UBound(entryList)).C_IP = ActiveSheet.Cells(i, C_IPColumn).Value
entryList(UBound(entryList)).rowNum = i
End If
Next i
End Sub
' Returns the Entry matching the passed-in C_IP
Function GetEntry(C_IP As String) As Entry
Dim i As Integer
' Loop through all stored entries and return the first whose C_IP matches that passed in
For i = 0 To UBound(entryList)
If entryList(i).C_IP = C_IP Then
GetEntry = entryList(i)
End If
Next i
End Function
' A quick and dirty way to get an empty Entry
Function GetEmptyEntry() As Entry
End Function