2016-11-22 23 views
1

我在許可證編號數據庫中有一列。我試圖確定這些數字是否合法。其中一項測試是確定是否有多個相同字符出現。我試圖確定最重複的角色的數量是多少。第二個測試是確定所有的數字是否都是順序的,但我將其作爲一個不同的問題發佈。Oracle SQL中重複字符的最大數量列

什麼我在尋找一個例子:

LICENSE_NUMBER MAX_COUNT 
111246544  3 
999999999  9 
123456789  0 
AAAAAAAAA  9 
A12345667  2 

感謝您的幫助!

回答

1

這不是最漂亮的代碼,如果許可證可以包含多個字符(我客串是十六進制),這將是很長的查詢,但你可以嘗試:

select licence_number, greatest(REGEXP_COUNT(licence_number, '1'), 
    REGEXP_COUNT(licence_number, '2'), REGEXP_COUNT(licence_number, '3'), 
    REGEXP_COUNT(licence_number, '4'), REGEXP_COUNT(licence_number, '5'), 
    REGEXP_COUNT(licence_number, '6'), REGEXP_COUNT(licence_number, '7'), 
    REGEXP_COUNT(licence_number, '8'), REGEXP_COUNT(licence_number, '9'), 
    REGEXP_COUNT(licence_number, '0'), REGEXP_COUNT(licence_number, 'A'), 
    REGEXP_COUNT(licence_number, 'B'), REGEXP_COUNT(licence_number, 'C'), 
    REGEXP_COUNT(licence_number, 'D'), REGEXP_COUNT(licence_number, 'E'), 
    REGEXP_COUNT(licence_number, 'F')) as max_count 
from table; 
+0

@ user961743它是你需要什麼,或者你想只計算連續的相同字符? – Kacper

+0

這似乎是我需要的。它確實使我的查詢執行時間增加了,但它適用於迄今爲止所嘗試的內容! –

0

假設在這種情況下:123456789的最重複的字符計數爲1 - 不爲0,那麼少的子查詢的查詢做的工作:

SELECT LICENSE_NUMBER, max(cnt) 
FROM (
    SELECT LICENSE_NUMBER, substr(LICENSE_NUMBER, x, 1) qq, count(*) As cnt 
    FROM (
     SELECT * 
     FROM table 
     CROSS JOIN (
      SELECT level x FROM dual 
      -- get a max length of lincence with the belo subquery 
      CONNECT BY LEVEL <= (SELECT MAX(length(LICENSE_NUMBER)) FROM table) 
     ) 
    ) 
    GROUP BY LICENSE_NUMBER, substr(LICENSE_NUMBER, x, 1) 
) 
WHERE qq IS NOT NULL 
GROUP BY LICENSE_NUMBER 
ORDER BY 1; 

如果你喜歡打印0而不是1,只是改變的第一行:

SELECT LICENSE_NUMBER, CASE max(cnt) WHEN 1 THEN 0 ELSE max(cnt) END 
FROM .... 
1

這是一種方法。要計算一個字符出現的次數(例如'x'),存在於像'zxxydds'這樣的字符串中,最快的方法是使用字符串函數REPLACE()從字符串中刪除所有出現的'x'(將'x'替換爲''),然後從原始字符串的長度中減去結果字符串的長度。必須小心謹慎,因爲如果字符串全部爲'x'(如'xxxxx'),則結果字符串爲空,Oracle中空字符串的長度爲NULL而不是零。因此,我們需要使用coalesce()的呼叫來使此長度爲零而不是NULL

其餘的是簡單的:在一個許可證號創建的所有可能字符的「假表」(例如,0-9A-F,但可以推廣到任何字符名單) - 我做一個簡單的table()函數 - 然後進行交叉連接,計算每個字符的出現次數,然後按license_number進行max()分組。我做了一個最後的簡化:如果C是一個常量(一個固定的數字),並且x的範圍超過一組,然後max(C-x) = C - min(x)

with 
    test_data (license_number) as (
     select '111246544' from dual union all 
     select '999999999' from dual union all 
     select '123456789' from dual union all 
     select 'AAAAAAAAA' from dual union all 
     select 'A12345667' from dual 
    ) 
-- end of test data; solution (SQL query) begins below this line 
select t.license_number, 
     length(t.license_number) - 
     min(coalesce(length(replace(t.license_number, c.column_value, '')), 0)) 
                 as max_count 
from test_data t cross join 
     table(sys.odcivarchar2list(
       '0','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F')) c 
group by t.license_number 
; 

LICENSE_NUMBER MAX_COUNT 
-------------- --------- 
AAAAAAAAA    9 
123456789    1 
A12345667    2 
999999999    9 
111246544    3 
1

下面是對同一問題的不同公式的解決方案。假設我們想在許可證號碼中找到相同字符的最大數量的連續出現次數。例如,如果許可證號是112211220,則1和2都出現4次。但是,同一字符的最大連續出現次數爲2.

此問題需要將每個許可證號碼拆分爲其各個字符,並跟蹤它們在字符串中的位置。我在第一次CTE中這樣做(「第一次」不包括測試數據,就是這樣)。然後,通過使用所謂的Tabibitosan方法(CTE使用兩個不同的電話號碼row_number()),通常可以最有效地識別連續的「某物」。之後,這是一個簡單的分組,計數和取最大值的問題。

with 
-- begin of test data, not part of the solution 
    test_data (license_number) as (
     select '111246544' from dual union all 
     select '999999999' from dual union all 
     select '123456789' from dual union all 
     select 'AAAAAAAAA' from dual union all 
     select 'A12345667' from dual union all 
     select '112211220' from dual 
    ), 
-- end of test data; solution (SQL query) continues below this line 
    tokenized (license_number, idx, ch) as (
     select license_number, level, substr(license_number, level, 1) 
     from test_data 
     connect by level <= length(license_number) 
      and prior license_number = license_number 
      and prior sys_guid() is not null 
    ), 
    prep (license_number, idx, ch, grp) as (
     select license_number, idx, ch, 
       row_number() over (partition by license_number order by idx) - 
       row_number() over (partition by license_number, ch order by idx) 
     from tokenized 
    ), 
    grouped (license_number, ch, grp, ct) as (
     select license_number, ch, grp, count(*) 
     from  prep 
     group by license_number, ch, grp 
    ) 
select license_number, max(ct) as max_count 
from  grouped 
group by license_number 
; 

輸出

LICENSE_NUMBER MAX_COUNT 
-------------- --------- 
AAAAAAAAA    9 
123456789    1 
A12345667    2 
999999999    9 
111246544    3 
112211220    2 
相關問題