2013年10月29日 星期二

取得具有相同數字之數值(2)

本範例將查詢具有相同數字之數值(如:11122888等),此範例將利用2組數值數列產生111111222….之數列,以 Table Join方式進行篩選,即可將符合相同數字之數值保留。SQL及結果如下:

SQL
MSSQL
WITH Filter
AS
(
--產生, 11, 111, 1111...數列
SELECT N.number
       , REPLICATE(CAST(N.number AS VARCHAR), D.number) Val_C
       , CAST(REPLICATE(CAST(N.number AS VARCHAR), D.number) AS BIGINT) Val
FROM master.dbo.spt_values N  -- 產生1~9數值數列
, master.dbo.spt_values D  -- 產生1~D(位數)數列
, (--重點.以取得最大數值,以為底取LOG即可得最大數值之位數(ex: 222為位數)
        SELECT CEILING(LOG10(MAX(Val))) Digits   -- 3. LOG值進位
                , LOG10(MAX(Val)) "Digits(LOG10)"   -- 2.最大數值以10為底取LOG
              , MAX(Val)          MaxVal           -- 1.取得最大數值
          FROM #Data
        ) U
WHERE 1=1
       AND N.name IS NULL
       AND D.name IS NULL
       AND N.number BETWEEN 1 AND 9        -- 產生~9數值數列
       AND D.number BETWEEN 1 AND U.Digits -- 產生~D(位數)數列
--ORDER BY N.number, D.number
)
------------
SELECT D.*
FROM #Data D, Filter F
WHERE D.Val = F.Val

: 重點在於虛線位置,以產生111111222….
ORACLE
WITH Filter
AS
(
--產生, 11, 111, 1111...數列
SELECT N.NUM
       , D.Digits
       , RPAD(N.NUM , D.Digits , N.NUM) VAL
FROM
    (
    SELECT LEVEL NUM
    FROM DUAL
    CONNECT BY LEVEL <=9
     ) N,
     (
    SELECT LEVEL Digits
    FROM DUAL,
         (
         SELECT CEIL(LOG(10, MAX(Val))) Digits
             , MAX(Val) MaxVal
         FROM TEST
         )
    CONNECT BY LEVEL <= Digits
     ) D
)
SELECT D.*
FROM TEST D, Filter F
WHERE D.Val = F.Val

執行結果如下:
             











SQL /說明
說明
MSSSQL
--產生, 11, 111, 1111...數列
SELECT N.number
,REPLICATE(CAST(N.number AS VARCHAR), D.number) Val_C
,CAST(REPLICATE(CAST(N.number AS VARCHAR), D.number) AS INT) Val
FROM master.dbo.spt_values N  -- 產生1~9數值數列
, master.dbo.spt_values D  -- 產生1~D(位數)數列
, (--重點.以取得最大數值,以為底取LOG即可得最大數值之位數(ex: 222為位數)
 SELECT CEILING(LOG10(MAX(Val))) Digits -- 3. LOG值進位
    , LOG10(MAX(Val)) "Digits(LOG10)"   -- 2.最大數值以10為底取LOG
       , MAX(Val)          MaxVal            -- 1.取得最大數值
    FROM #Data
    ) U
WHERE 1=1
       AND N.name IS NULL
       AND D.name IS NULL
       AND N.number BETWEEN 1 AND 9        -- 產生~9數值數列
       AND D.number BETWEEN 1 AND U.Digits -- 產生~D(位數)數列
--ORDER BY N.number, D.number
ü   利用2組數值數列產生111111222…
ü   1組數列為1~9;第2組為1~{最大位數}
ü   最大位數是以
- 取得最大數值
- 最大數值取LOG10
- 再以CEILING函數無條件進位,即為最大位數。
ü   REPLICATE函數為將字串值重複指定的次數。以產生重複數字數值字串。
ü   數值字串轉型為數字。

ORACLE
--產生, 11, 111, 1111...數列
SELECT N.NUM
       , D.Digits
       , RPAD(N.NUM , D.Digits , N.NUM) VAL
FROM
    (
    SELECT LEVEL NUM
    FROM DUAL
    CONNECT BY LEVEL <=9
     ) N,
     (
    SELECT LEVEL Digits
    FROM DUAL,
         (
         SELECT CEIL(LOG(10, MAX(Val))) Digits
             , MAX(Val) MaxVal
         FROM TEST
         )
    CONNECT BY LEVEL <= Digits
     ) D
ü   ORACLEREPLICATE函數,可使用RPAD函數替代。
ü   其餘概念與MSSQL同,略。
此方法虛線部分執行結果如下(9*3 =27筆):



沒有留言:

張貼留言