2011-09-23 20 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子句中,因为我的算术是错误的或者你的规格是错误的。