2011-09-23 51 views
0

我想從表中選擇具有以下規則的數據,但我在編寫查詢時遇到了問題。我使用的是PostgreSQL,我無法創建UDF。該表是這樣的:驗證帳號SQL表

id | user_id | account_number 
------------------------------- 
1 | 1  | 12345671 
2 | 4  | 12356673 
3 | 7  | 12325678 

ID和user_ID的是整數,而賬號是一個字符串。我想選擇符合以下條件的帳戶號碼:

  • 帳號字符串包含正好8個數字
  • 驗證方案
    1. 在第一個7個位數
    2. 乘第一個數字由1,第2乘2,第3乘3,第4乘1,第5乘2,第6乘3,第7乘1
    3. 將各位數乘以相關數的結果
    4. 如果第8位是一樣的MOD(總和,10),然後選擇這個數

在上面此表中,我只應的前兩行與查詢返回。

只是重複一遍,我不能創建一個UDF,所以我正在查找這是否可以在查詢中使用普通SQL。

謝謝!

+0

對於id = 1的行,總和爲1 + 2 * 2 + 3 * 3 + 4 + 5 * 2 + 6 * 3 + 7 = 53,這對mod(53,10)產生3。所以我不明白爲什麼這行應該返回最後一位是1而不是3 –

+0

UDF應該代表用戶定義的函數或用戶定義的字段? –

回答

2

是的,你可以做到。基本上,使用SIMILAR TO檢查8位數字,然後使用子字符串進行數學計算。事情是這樣的:

SELECT * FROM table_name WHERE 
    account_number SIMILAR TO '[0-9]{8}' 
    AND (
    1 * CAST(SUBSTR(account_number, 1, 1) AS INTEGER) + 
    2 * CAST(SUBSTR(account_number, 2, 1) AS INTEGER) + 
    3 * CAST(SUBSTR(account_number, 3, 1) AS INTEGER) + 
    1 * CAST(SUBSTR(account_number, 4, 1) AS INTEGER) + 
    2 * CAST(SUBSTR(account_number, 5, 1) AS INTEGER) + 
    3 * CAST(SUBSTR(account_number, 6, 1) AS INTEGER) + 
    1 * CAST(SUBSTR(account_number, 7, 1) AS INTEGER) 
)%10 = CAST(SUBSTR(account_number, 8, 1) AS INTEGER) 

當然,這將返回沒有排在你的榜樣,因爲:

1×1 + 2×2 + 3x3 + 1×4 + 2×5 + 3×6 + 1×7 = 53 
53 MOD 10 = 3 
3 ≠ 1 

PS:你一定要明白的UDF也可以用比CEG,你的其他語言編寫可以在PL/pgSQL中編寫一個。

0

只需創建一個表格,您可以分開數字,然後進行算術運算(當然,您可以填寫...的其餘部分)。

create table digits as 
select account_number, 
substr(account_number::text,0,1)::int as digit_1 
,substr(account_number::text,1,1)::int as digit_2 
,... 
substr(account_number::text,7,1) as digit_8 
from table 
where account_number::text~E'[0-9]{8}'; --regex to make sure acct numbers are of the right form. 

select account_number, 
(digit_1+2*digit_2+...+3*digit_6+dight_7)%10=digit_8 as valid 
from digits; 

當然,如果你不想創建一個單獨的表,你可以隨時把select語句創建digits表爲子查詢的第二個查詢。

0
select id, 
     user_id, 
     digit_sum, 
     last_digit 
from (
    select id, 
     user_id, 
     (substring(account_number,1,1)::int + 
      substring(account_number,2,1)::int * 2 + 
      substring(account_number,3,1)::int * 3 + 
      substring(account_number,4,1)::int + 
      substring(account_number,5,1)::int * 2 + 
      substring(account_number,6,1)::int * 3 + 
      substring(account_number,7,1)::int) as digit_sum, 
      substring(account_number,8,1)::int as last_digit 
    from accounts 
) t 
where last_digit = digit_sum % 10 

爲了讓生活更輕鬆,我會創建一個視圖,對值進行拆分和求和。然後,您只需從該視圖中選擇我用於派生表的where條件。

0

你可以嘗試沿着這些線。

select *, (
    (substring(account_number from 1 for 1)::integer * 1) + 
    (substring(account_number from 2 for 1)::integer * 2) + 
    (substring(account_number from 3 for 1)::integer * 3) + 
    (substring(account_number from 4 for 1)::integer * 1) + 
    (substring(account_number from 5 for 1)::integer * 2) + 
    (substring(account_number from 6 for 1)::integer * 3) + 
    (substring(account_number from 7 for 1)::integer * 1) 
    ) as sums, 
    (
    (substring(account_number from 1 for 1)::integer * 1) + 
    (substring(account_number from 2 for 1)::integer * 2) + 
    (substring(account_number from 3 for 1)::integer * 3) + 
    (substring(account_number from 4 for 1)::integer * 1) + 
    (substring(account_number from 5 for 1)::integer * 2) + 
    (substring(account_number from 6 for 1)::integer * 3) + 
    (substring(account_number from 7 for 1)::integer * 1) 
    ) % 10 as mod_10 
from acct_no 
where length(account_number) = 8 

我把計算寫入SELECT子句而不是WHERE子句中,因爲我的算術是錯誤的或者你的規格是錯誤的。