返回五行随机 DNA 而不是一
Posted
技术标签:
【中文标题】返回五行随机 DNA 而不是一【英文标题】:Return five rows of random DNA instead of just one 【发布时间】:2020-04-30 22:01:19 【问题描述】:这是我必须创建一串 DNA 的代码:
prepare dna_length(int) as
with t1 as (
select chr(65) as s
union select chr(67)
union select chr(71)
union select chr(84) )
, t2 as ( select s, row_number() over() as rn from t1)
, t3 as ( select generate_series(1,$1) as i, round(random() * 4 + 0.5) as rn )
, t4 as ( select t2.s from t2 join t3 on (t2.rn=t3.rn))
select array_to_string(array(select s from t4),'') as dna;
execute dna_length(20);
我试图弄清楚如何重写它以给出一个包含 5 行 DNA 字符串的表,每行长度为 20,而不仅仅是一行。这是针对 PostgreSQL 的。
我试过了:
CREATE TABLE dna_table(g int, dna text);
INSERT INTO dna_table (1, execute dna_length(20));
但这似乎不起作用。我是一个绝对的初学者。如何正确执行此操作?
【问题讨论】:
【参考方案1】:PREPARE 创建一个可以“按原样”使用的准备好的语句。如果您准备好的语句返回一个字符串,那么您只能得到一个字符串。您不能在其他操作中使用它,例如插入,例如
在您的情况下,您可以创建一个函数:
create or replace function dna_length(int) returns text as
$$
with t1 as (
select chr(65) as s
union
select chr(67)
union
select chr(71)
union
select chr(84))
, t2 as (select s,
row_number() over () as rn
from t1)
, t3 as (select generate_series(1, $1) as i,
round(random() * 4 + 0.5) as rn)
, t4 as (select t2.s
from t2
join t3 on (t2.rn = t3.rn))
select array_to_string(array(select s from t4), '') as dna
$$ language sql;
并以这样的方式使用它:
insert into dna_table(g, dna) select generate_series(1,5), dna_length(20)
来自官方doc:
PREPARE 创建一个准备好的语句。准备好的语句是可用于优化性能的服务器端对象。当 PREPARE 语句被执行时,指定的语句被解析、分析和重写。当随后发出 EXECUTE 命令时,计划并执行准备好的语句。这种分工避免了重复的解析分析工作,同时允许执行计划依赖于提供的特定参数值。
关于functions。
【讨论】:
【参考方案2】:这可以更简单、更快:
SELECT string_agg(CASE ceil(random() * 4)
WHEN 1 THEN 'A'
WHEN 2 THEN 'C'
WHEN 3 THEN 'T'
WHEN 4 THEN 'G'
END, '') AS dna
FROM generate_series(1,100) g -- 100 = 5 rows * 20 nucleotides
GROUP BY g%5;
random() 产生random value in the range 0.0 <= x < 1.0
。乘以 4 并用ceil() 取数学上限(比round()
便宜),你会得到数字 1-4 的随机分布。转换为 ACTG,并与 GROUP BY g%5
- %
being the modulo operator 聚合。
关于string_agg()
:
作为准备好的语句,取$1
... 行数$2
... 每行核苷酸数
PREPARE dna_length(int, int) AS
SELECT string_agg(CASE ceil(random() * 4)
WHEN 1 THEN 'A'
WHEN 2 THEN 'C'
WHEN 3 THEN 'T'
WHEN 4 THEN 'G'
END, '') AS dna
FROM generate_series(1, $1 * $2) g
GROUP BY g%$1;
呼叫:
EXECUTE dna_length(5,20);
结果:
|脱氧核糖核酸 | | :-------------------- | | ATCTTCGACACGTCGGTACC | | GTGGCTGCAGATGAACAGAG | | ACAGCTTAAAACACTAAGCA | | TCCGGACCTCTCGACCTTGA | | CGTGCGGAGTACCCTAATTA |db小提琴here
如果您非常需要它,请考虑使用函数。见:
What is the difference between a prepared statement and a SQL or PL/pgSQL function, in terms of their purposes?【讨论】:
以上是关于返回五行随机 DNA 而不是一的主要内容,如果未能解决你的问题,请参考以下文章