我可以保持 INNER JOIN 的输出根据左侧表(第一个表)的顺序进行排序吗?

Posted

技术标签:

【中文标题】我可以保持 INNER JOIN 的输出根据左侧表(第一个表)的顺序进行排序吗?【英文标题】:Can I maintain the output of INNER JOIN to be sorted based on the order of the left side table (the 1st table)? 【发布时间】:2014-10-12 23:52:06 【问题描述】:

在 PostgreSQL 中 - 在以下查询中,我对两个表执行 INNER JOIN - 第一个表 (patient_bvi_p) 已排序。我从“id4”列中提取基因名称(一个简单的字符串),然后使用该值与第二个表(geneexpressoin17p)执行INNER JOIN。

我的问题是,在执行 INNER JOIN 之后,我的查询结果都被打乱了。 当我真的需要/希望它们时,这些行不再根据左侧表 (patient_bvi_p) 进行排序。

有人能解释一下在执行 INNER JOIN 后应该期待什么行为吗?不应该以与左(/第一)表的排序方式相同的方式对输出进行排序吗? 有没有办法以某种方式维持原始订单?或者 - 我应该总是假设在 INNER JOIN 之后结果输出是未排序的(=scrambled) - 因此我应该在执行 INNER 连接之后执行额外的排序步骤?... 我的动机基本上是避免额外的排序步骤并依赖于我的第一个表的原始顺序。

select
    t1.* ,
    bvi_d_exp,
    bvi_r_exp,
    bvi_exp.bvi_lr_rvd
into Patient_bvi_p_exp
from
    (
        select split_part(id4, '@', 3) genes, *
        from patient_bvi_p
    ) t1
    inner join (
        select
            genename,
            bvi_d_exp,
            bvi_r_exp,
            bvi_lr_rvd
        from geneexpression17p
    ) bvi_exp on lower(t1.genes) = lower(bvi_exp.genename)

【问题讨论】:

添加一个Order By 子句。 SQL,就其本质而言,是未排序的。您需要明确告诉它您希望它如何排序,否则它不会。 顺便说一句:存储基因名称区分大小写是否有意义? (对我来说不是) 【参考方案1】:

第一个表 (patient_bvi_p) 已排序

SQL 中没有“排序”表。如果您想要排序结果,请使用order by 子句

【讨论】:

【参考方案2】:

如果没有 order by 子句,则查询输出中的行顺序未定义。 Postgres 将以它认为合适的任何方式输出。如果要对输出进行排序,则必须指定 order by。换句话说,你不应该像你描述的那样依赖输出顺序,如果没有指定它可能会改变。也就是说,在您的示例中:

select t1.* ,bvi_d_exp,bvi_r_exp,bvi_exp.bvi_lr_rvd
  into Patient_bvi_p_exp
  from (select split_part(id4, '@', 3)genes,* from patient_bvi_p)
  t1 inner join (select genename,bvi_d_exp,bvi_r_exp,bvi_lr_rvd
  from geneexpression17p) bvi_exp on lower(t1.genes)= lower(bvi_exp.genename);

我想你是说如果你这样做:

select * from Patient_bvi_p_exp;

你得到随机排序。是的,这是真的。同样,不要依赖顺序。但是,您可以:

select t1.* ,bvi_d_exp,bvi_r_exp,bvi_exp.bvi_lr_rvd
  into Patient_bvi_p_exp
  from (select split_part(id4, '@', 3)genes,* from patient_bvi_p)
  t1 inner join (select genename,bvi_d_exp,bvi_r_exp,bvi_lr_rvd
  from geneexpression17p) bvi_exp on lower(t1.genes)= lower(bvi_exp.genename)
  order by bvi_d;

这将导致您的表格按 bvi_d 列(或任何您想要的)排序。因此,对该表的简单选择可能会以正确的顺序返回它。或者,如果您已经运行了第一个查询,您可以:

create index whatever on Patient_bvi_p_exp(bvi_d);
cluster Patient_bvi_p_exp using whatever;

这将对表格进行物理重新排序,以便简单的选择会按照您想要的顺序返回它。

我不得不再说一遍,你这样做更安全:

select * from Patient_bvi_p_exp order by bvi_d;

【讨论】:

按 bvi_d 排序不会得到我想要的结果。我的左侧表格最初不是按 bvi_d 排序的,而是通过考虑染色体数量和基因组位置的相当复杂的方式排序的。该排序步骤是作为表“patient_bvi_p”制作的一部分执行的。我在 patient_bvi_p 中没有可以立即参考以便按此表重新排序的特定列。该表的排序是多步骤过程的组合。它可能应该将序列号列添加到我的左侧表中,以便在 INNER JOIN 之后使用我,以便根据我的结果进行处理 我可以使用:ALTER TABLE Patient_bvi_p ADD COLUMN columnName serial NOT NULL;但是 - 我想知道是否可以在“实时”查询期间添加此序列号列,而不是在运行查询之前添加此化妆品...?

以上是关于我可以保持 INNER JOIN 的输出根据左侧表(第一个表)的顺序进行排序吗?的主要内容,如果未能解决你的问题,请参考以下文章

多表查询-inner join left join right joinfull join

SQL INNER JOIN - 根据另一行的值从另一个表中选择数据

sql中的inner join ,left join ,right join

使用 INNER JOIN 从两个表中删除数据

SQL中inner join,outer join和cross join的区别

SQL——左连接(Left join)右连接(Right join)内连接(Inner join)