簡體   English   中英

SQL Developer-您可以在游標中使用case語句返回多個值

[英]Sql Developer - Can you use a case statement in a cursor to return multiple values

我一直在嘗試將數百萬行數據分類為各種不同主題的任務。 數據涉及來自我們客戶支持的呼叫,我們正在嘗試找到一種將每個呼叫分類為109個主題之一的方法。 由於數據的機密性,我無法透露任何實際數據,但會嘗試提供其他人可以比較的相關數據子集。

數據:

Incident_Number | 通話說明
000123456 | 桔子和蘋果的問題
000987654 | 橘子
004567891 | 蘋果和獼猴桃
026589741 | 獼猴桃的問題

SQL:

選擇
Incident_Number,
通話說明,
(如果call_description如“%oranges%”,則為橙色
當call_description喜歡'%apples%'時,apples
當call_descritpion喜歡'%kiwis%'然后'kiwis'
否則為“未分類”末)主題
來自DATA

我希望將事件000123456歸類為桔子和蘋果,而事件004567891被歸類為蘋果和奇異果。

期望的輸出

Incident_Number | Call_Description ............................... | 話題
000123456 ........ | 桔子和蘋果的問題| 橘子
000123456 ........ | 桔子和蘋果的問題| 蘋果
000987654 ........ | 橘子.................................... | 橘子
004567891 ......... | 蘋果和獼猴桃...... 蘋果
004567891 ......... | 蘋果和獼猴桃...... 奇異果
026589741 ......... | 奇異果問題....................................... | 奇異果

包起來

根據我的有限知識以及我從研究中獲得的經驗,一個簡單的案例陳述無法做到這一點,因為它在找到第一個真實價值后便短路了。 我的問題是是否可以對我的代碼進行一些更改,或者以某種方式設置一個游標以遍歷我的初始表並為我提供上述所需的輸出。

感謝您提供的任何幫助或建議,並希望我遵守該網站的規定(誠實地保存了我的屁股!)

問候,理查德

我使用Microsoft SQL Server代替Oracle,所以我不確定Oracle語法,但是我過去使用的一種解決方案是創建一個臨時表:

CREATE GLOBAL TEMPORARY TABLE my_temp_table (
  groupName  varchar(50)
) ON COMMIT DELETE ROWS;
Insert Into my_temp_table (groupName) VALUES('oranges')
Insert Into my_temp_table (groupName) VALUES('apples')
Insert Into my_temp_table (groupName) VALUES('kiwis')

然后我將內部聯接到表以復制記錄:

select
    Incident_Number,
    Call_Description,
    my_temp_table.groupName Topic
from DATA
inner join my_temp_table
    on Data.call_description like '%' + my_temp_table.groupName + '%'

這種方法的一個問題是,如果記錄不屬於任何類別,它將被完全排除。

我的示例適用於MS SQL Server: http ://www.sqlfiddle.com/#!3/8e904 /2

您可以創建一個包含詳細信息的表,並使用它進行簡單的交叉連接

create table data(
Incident_Number varchar(9),
Call_Description varchar(50))

create table detail(detail varchar(20))

insert into data select

'000123456','Issue with oranges and apples'
union select
'000987654', 'oranges '
union select
'004567891', 'with apples and kiwis'
union select
'026589741', 'Issue with kiwis'

insert into detail select 'kiwis'
union select 'oranges'
union select 'apples'

select * from data a
 cross join detail b
where a.call_description like '%'||b.detail||'%'
order by a.Incident_Number

添加新版本http://www.sqlfiddle.com/#!3/b3378/1

它管理所有事件,以空值識別沒有巧合的事件

select * from data a
 left join detail b
on a.call_description like '%'||b.detail||'%'

一種選擇是(物理地或虛擬地)創建關鍵字表,並使用該表聯接到數據表中。 就像是

WITH keywords AS (
  SELECT 'apples' topic FROM dual UNION 
  SELECT 'oranges' FROM dual UNION 
  SELECT 'kiwis' FROM dual
)
SELECT data.incident_number,
       data.incident_description,
       keywords.topic
  FROM data
       JOIN keywords
         ON( data.incident_description LIKE '%' || keywords.topic || '%' )

這將起作用,但這不是世界上最有效或最靈活的方法。 它不能很好地處理單詞的不同形式(例如,如果描述引用了單數的“蘋果”)。 它不處理出現在其他單詞中的單詞(例如,如果描述中提到“ crabapples”)。 而且,它會根據對整個incident_description掃描來進行相對較慢的匹配。

一種替代方法是使用Oracle Text索引您的數據。 這可能是一個更復雜的解決方案,但它將更加靈活並且應該更加高效。

我使用CURSOR選項來遍歷表中的記錄,並使用類別信息更新每一行。

因為您提到您的規則非常復雜,所以我認為每個規則都需要在此過程中手寫,而不是存儲在表中。

抱歉,這是MSSQL,因此可能需要為Oracle進行一些轉換。

/*BEGIN SETUP TEMP DATA*/
CREATE TABLE #tmp1 (
    idno int,
    title nvarchar(100),    
    Categories nvarchar(100) --I have added this row to my temp data, you could store this in another table if needed.
)

INSERT INTO #tmp1 (idno, title) VALUES (1, 'problem apples and oranges')
INSERT INTO #tmp1 (idno, title) VALUES (2, 'problem with apples')
INSERT INTO #tmp1 (idno, title) VALUES (3, 'problem with oranges')
INSERT INTO #tmp1 (idno, title) VALUES (4, 'problem with kiwis')
INSERT INTO #tmp1 (idno, title) VALUES (5, 'problem with something')
/*END SETUP TEMP DATA*/

/*SETUP VARIABLES TO USE IN CURSOR*/
DECLARE @idno int,
        @title nvarchar(100)

/*DECLARE CURSOR, OPEND IT AND FETCH DATA INTO INTO IT*/
DECLARE incident_cursor CURSOR FOR 
    SELECT idno, title
    FROM #tmp1 --You could add WHERE Categories IS NULL to only update records that have not been processed
OPEN incident_cursor

FETCH NEXT FROM incident_cursor 
INTO @idno, @title

/*LOOP THROUGH CURSOR*/
WHILE @@FETCH_STATUS = 0
BEGIN

    DECLARE @allCategories nvarchar(100)

    SET @allCategories = ''

    /*WRITE RULES HERE TO WORK OUT WHETHER CATEGORY NEEDS ADDING*/
    IF (@title LIKE '%apples%') BEGIN SET @allCategories = @allCategories + 'Apples ' END
    IF (@title LIKE '%oranges%') BEGIN SET @allCategories = @allCategories + 'Oranges ' END
    IF (@title LIKE '%kiwis%') BEGIN SET @allCategories = @allCategories + 'Kiwis ' END

    IF @allCategories = '' BEGIN SET @allCategories = 'Uncategorised' END

    /*UPDATE ORIGINAL TABLE WITH CATEGORY INFORMATION*/
    UPDATE #tmp1 SET Categories = @allCategories WHERE idno = @idno

FETCH NEXT FROM incident_cursor 
    INTO @idno, @title
END 
CLOSE incident_cursor;
DEALLOCATE incident_cursor;

/*THIS ARE JUST TO DISPLAY OUTPUT AND CLEAR UP TEST DATA*/
SELECT * FROM #tmp1

DROP TABLE #tmp1

您可以將其設置為在計划的作業中運行,以根據需要頻繁更新記錄。

可能不是您的理想解決方案,但希望是一個起點

抱歉,我花了多長時間才回來。 我陷入了一些更加緊迫的可交付成果。 最后,我通過將查詢存儲在一個表中作為記錄,然后使用execute立即執行命令來運行,從而弄清楚了如何使其工作。 我已在下面提供了代碼,以防將來有人使用。

create table text_kw_search_queries
(
incident_number varchar2(15),
description varchar2(100),
topic_level_1 varchar2(89),
topic_level_2 varchar2(89)
);

DECLARE 
V_SQL VARCHAR2(1000);
CURSOR UPTO IS
SELECT TOPIC_level_1, TOPIC_level_2, description FROM tcstopic
;

BEGIN
FOR i IN UPTO LOOP

V_SQL := 'INSERT /*+APPEND PARALLEL(TEXT_KW_SEARCH_LOOP,2)*/ INTO text_kw_search_queries
SELECT
t2.Incident_Number,
t2.description,
t2.TOPIC_level_1,
t2.TOPIC_level_2
FROM (
SELECT 
t1.Incident_number,
t1.description,
'''||i.TOPIC_level_1||''' AS TOPIC_level_1, 
'''||i.TOPIC_level_2||''' AS TOPIC_level_2,
(CASE WHEN '|| i.description ||' THEN 1 ELSE 0 END) as FLAG
FROM cso_text_query t1
) t2
WHERE t2.FLAG = 1';

EXECUTE IMMEDIATE V_SQL;
DBMS_OUTPUT.PUT_LINE(V_SQL);

COMMIT WORK;
END LOOP;
END;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM