我想从具有以下规则的表中选择数据,但是我在编写查询时遇到了问题。我正在使用PostgreSQL,我无法创建UDF。该表如下所示:
id | user_id | account_number
-------------------------------
1 | 1 | 12345671
2 | 4 | 12356673
3 | 7 | 12325678
id和user_id是整数,而帐号是字符串。我想选择符合以下条件的帐号:
在上表中,我只应该返回带有查询的前两行。
重复一遍,我无法创建UDF,所以我希望找出在查询中使用普通SQL是否可行。
谢谢!
答案 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子句,因为我的算法错误或你的规范是错误的。