2013年10月26日 星期六

取得具有相同數字之數值

本範例將查詢具有相同數字之數值(如:11122888等),主要撰寫概念是以每個數值第一個數字(即最大位數)為除數,除以整個數值,若商數均為數字1、如111111…等,即代表此數值每個數字相同。MSSQLORACLE均應用相同概念撰寫,SQL及結果如下:

SQL
MSSQL
SELECT D.VAL
 , N.Num
 , D.VAL / N.Num Quotient --重點2.{數值}除以{數值}1碼之{數字}得到商數,均為1者即為所求
 , PATINDEX('%[^1]%',CAST((D.VAL/N.Num) AS varchar)) Pos --重點3.商數第1個數字不為1之位置
FROM
(
 SELECT Val
 FROM (VALUES (1), (2), (3), (11), (121), (21), (22), (36), (116), (222)
          ) AS Data(Val)
) D,
     (--產生{1~9}數值數列,取自master.dbo.spt_values
      SELECT CAST(number AS VARCHAR)  Num
      FROM master.dbo.spt_values
      WHERE name IS NULL
           AND number BETWEEN 1 AND 9
     ) N
WHERE 1=1
AND D.VAL LIKE N.Num + '%' --重點1.{數值第1}{數字1~9}進行Table Join
--AND PATINDEX('%[^1]%', CAST((D.VAL / N.Num) AS VARCHAR)) = 0
ORDER BY N.NUM, D.VAL
: VAULES2008功能,先前文章以介紹,請自行參考不贅述。

ORACLE
SELECT D.Val
 , N.Num
 , TRUNC(D.VAL/N.Num) Quotient --重點2.{數值}除以{數值}1碼之{數字}得到商數,均為1者即為所求
 , REGEXP_INSTR(TRUNC(D.VAL/N.Num), '[^1]') Pos --重點3.商數第1個數字不為1之位置
FROM
(
  SELECT Column_Value AS Val
  FROM TABLE(Split_tbl('1','2','3','11','121','21','22','36','121','222'))
) D,
  (--產生{1~9}數值數列,CONNECT BY產生
  SELECT LEVEL Num
  FROM DUAL
  CONNECT BY LEVEL <=9
  ) N
WHERE 1=1
      AND D.VAL LIKE N.Num ||'%' --重點1.{數值第1}{數字1~9}進行Table Join
      --AND REGEXP_INSTR(TRUNC(D.VAL/N.Num), '[^1]') = 0
ORDER BY N.NUM, D.VAL

: Split_tbl為自訂type配合table函數,可將CSV字串轉為Table,後續文章再行介紹。
:虛線段落如無法瞭解,可自行CREATE TABLE / INSERT TABLE建立測試資料。

重點1: Join方式得到數值第一個數字。
重點2: 將數值除以第一個數字,若商數之數字均為1,則代表其數字均相同。商數取得方法『數值函數』之說明。
重點3: Regular Expression找出商數中第一個非為1之位置,如均為1則回傳為0MSSQL可應用PATINDEX函數;ORACLE則可使用REGEXP_INSTR,可參閱拙著或後續文章將說明。


執行結果
說明

欄位說明
ü   VAL: 數值
ü   NUM: 數值第1碼數字
ü   Quotient: VAL除以NUM之商數
ü   Pos:不為1之數字位置,0代表均為1

 Pos0者,即為所求,實際應用時,將WHERE條件式中註解該行啟用即可。執行結果如下:

沒有留言:

張貼留言