验证帐号SQL表

时间:2011-09-23 21:17:40

标签: sql postgresql

我想从具有以下规则的表中选择数据,但是我在编写查询时遇到了问题。我正在使用PostgreSQL,我无法创建UDF。该表如下所示:

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

id和user_id是整数,而帐号是字符串。我想选择符合以下条件的帐号:

  • 帐号字符串包含8位数字
  • 验证方案
    1. 取前7位
    2. 将第一个数字乘以1,将第二个数字乘以2,将第三个数字乘以3,将第四个数字乘以1,将第五个乘以2,将第六个乘以3,将第七个乘以1
    3. 将每个数字乘以相关数字
    4. 的结果相加
    5. 如果第8位与mod(sum,10)相同,则选择此数字

在上表中,我只应该返回带有查询的前两行。

重复一遍,我无法创建UDF,所以我希望找出在查询中使用普通SQL是否可行。

谢谢!

4 个答案:

答案 0 :(得分: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)

当然,这会在您的示例中返回 no 行,因为:

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

PS:您确实意识到UDF可以用C语言以外的语言编写。例如,您可以在PL / pgSQL中编写一个。

答案 1 :(得分: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语句放入第二个查询的子查询中。

答案 2 :(得分: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条件。

答案 3 :(得分: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子句,因为我的算法错误或你的规范是错误的。