返回五行随机DNA,而不是仅返回一行

问题描述 投票:1回答:2

这是创建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行长度为20的DNA字符串组成的表,而不只是一行。这是针对PostgreSQL的。

我尝试过:

CREATE TABLE dna_table(g int, dna text);
INSERT INTO dna_table (1, execute dna_length(20));

但是这似乎不起作用。我是绝对的初学者。如何正确执行此操作?

sql postgresql random prepared-statement set-returning-functions
2个回答
0
投票

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


0
投票

这可以更简单,更快:

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()

作为准备好的陈述,Concatenate multiple result rows of one column into one, group by another column...行数$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;

结果:

| dna || :------------------- || ATCTTCGACACGTCGGTACC || GTGGCTGCAGATGAACAGAG || ACAGCTTAAAACACTAAGCA || TCCGGACCTCTCGACCTTGA || CGTGCGGAGTACCCTAATTA |

db <>小提琴EXECUTE dna_length(5,20);

如果您非常需要它,请考虑使用一个函数。参见:

© www.soinside.com 2019 - 2024. All rights reserved.