将具有重复列名的SQL中的表联接为点表示法,而不必使用别名列出每个列

时间:2019-07-09 21:09:24

标签: javascript sql postgresql sequelize.js

我猜这个问题会经常出现,这是我的一些错误步骤和设计缺陷的结果,但是我有点卡住了,而且我也不知道去哪里看,因为我也SQL新手。

此事的基本要点是,我开始使用Sequelize构建应用程序,该程序具有include函数,该函数本质上将表作为嵌套对象进行连接。但是现在Sequelize对我不起作用,我需要进行原始查询,但是我仍然有依赖于Sequelize给出的结构的应用程序代码。基本上,我需要重新创建Sequelize包含功能,但不是那么冗长。

因此,在详细介绍环境之前,请先进行总结:PostgreSQL和带有Sequelize&Knex的JavaScript(用于以编程方式帮助构建查询)。

所以我有表foo

id | name | bar_id
---+------+-------
1  | Joe  | 1
2  | Jan  | 2

bar

id | pet | vet_id
---+-----+-------
1  | cat | 1
2  | dog | 1

vet

id | name
---+-----
1  | Dr. Elsey

理想的结果如下所示:

id | name | bar.id | bar.pet | bar.vet.id | bar.vet.name
---+------+--------+---------+------------+-------------
1  | Joe  | 1      | cat     | 1          | Dr. Elsey
2  | Jan  | 2      | dog     | 1          | Dr. Elsey

Sequelize通过执行以下操作来实现此目的(对select进行释义):

select
  foo.id,
  foo.name,
  bar.id as "bar.id",
  bar.pet as "bar.pet",
  "bar->vet".id as "bar.vet.id",
  "bar->vet".name as "bar.vet.name"
from foo
  left outer join bar on foo.bar_id = bar.id
  left outer join vet as "bar->vet" on bar.vet_id = vet.id;

是否有任何方法可以不枚举所有这些选择别名?还是我可以尝试更好的输出?

基本上我想构建这样的对象:

{
  id: 1,
  name: 'Joe',
  bar: {
    id: 1,
    pet: 'cat',
    vet: {
      id: 1,
      name: 'Dr. Elsey'
    }
  }
};

1 个答案:

答案 0 :(得分:1)

我不会将其归类为更容易或更必要的分类(肯定会更复杂),但是如果您真的想避免别名,则可以尝试一些 SQL 元编程使用 Postgres的内置information_schema.columns表为您生成动态的 SQL

与此类似的东西可以满足您的确切需求:

select ' select json_agg(x) from (select '
      || array_to_string(array_agg(table_schema
      || '.' || table_name || '.'
      || column_name || ' as "' || table_schema || '.' || table_name || '.'
      || column_name || '"'), ', ') ||
   ' from public.foo join public.bar using(id)) as x'
from information_schema.columns 
where table_schema = 'public'
  and table_name in ('foo', 'bar');

上面的查询将以带有全模式限定列的JSON blob返回每一行。您可以使用Postgres的其他内置JSON functions进行修改以满足您的需求。

注意:在构造这样的查询时,请务必注意 SQL注入的潜力。也就是说,如果最终将脚本中的其他变量插入到此动态生成的SQL中,请务必小心。如果您发现自己需要这样做,则可以将动态SQL包装在您创建的纯SQL函数中,该函数使用绑定变量并将其作为参数,如Bobby Tables网站上所述。