排除联接中的重复字段

6 sql postgresql join left-join

我有一个数据集,我正在做分析.事实证明,人口统计和社区数据可以很容易地丰富,大大提高了分析结果.

为了做到这一点,我在进行分析之前加入了人口统计和社区数据.我需要从我的核心示例集中排除一些字段,所以我的连接看起来像这样:

select sampledata.c1, 
       sampledata.c2, 
       demographics.*, 
       community.* 
from sample data 
    join demographics using (zip) 
    join community using (fips)
Run Code Online (Sandbox Code Playgroud)

这会在输出中为我提供多个zip或fips列,而我的分析引擎无法处理这些列.我无法手动指定每个字段 - 浓缩表最终导致数百列.

我可以选择*,但是我会得到我不想要的样本数据中的所有列.

如何在不重复字段的情况下加入我的浓缩数据,同时仍然从样本表中选择我想要的列?

我有一个想法,如果postgres(我的数据库)可以完全限定输出中的每一列(如sample.c1,demographics.c1等),我会非常满意.

Syb*_*eus 2

SQL 中没有列排除语法,只有列包含语法(通过所有列的 * 运算符,或显式列出列名称)。

仅生成您想要的列的列表

但是,您可以使用模式表和数据库的一些内置函数生成包含数百个列名的 SQL 语句,减去您不需要的几个重复列。

SELECT
    'SELECT sampledata.c1, sampledata.c2, ' || ARRAY_TO_STRING(ARRAY(
        SELECT 'demographics' || '.' || column_name
        FROM information_schema.columns
        WHERE table_name = 'demographics' 
        AND column_name NOT IN ('zip')
        UNION ALL
        SELECT 'community' || '.' || column_name
        FROM information_schema.columns
        WHERE table_name = 'community' 
        AND column_name NOT IN ('fips')
    ), ',') || ' FROM sampledata JOIN demographics USING (zip) JOIN community USING (fips)'
AS statement
Run Code Online (Sandbox Code Playgroud)

这只会打印出语句,不会执行它。然后你只需复制结果并运行它。

如果您想一次性动态生成和运行该语句,那么您可以在PostgreSQL 文档中阅读如何运行动态 SQL 。

在表名前面加上列名

或者,这会生成所有列的选择列表,包括那些具有重复数据的列,但随后为它们添加别名以包含每列的表名称。

SELECT
    'SELECT ' || ARRAY_TO_STRING(ARRAY(
        SELECT table_name || '.' || column_name || ' AS ' || table_name || '_' || column_name
        FROM information_schema.columns
        WHERE table_name in ('sampledata', 'demographics', 'community')
    ), ',') || ' FROM sampledata JOIN demographics USING (zip) JOIN community USING (fips)'
AS statement
Run Code Online (Sandbox Code Playgroud)

同样,这只会生成语句。如果您想要动态生成和运行该语句,那么您需要温习数据库的动态 SQL 执行,否则只需复制并运行结果。

如果您确实想要在列别名中使用点分隔符,那么您必须使用双引号别名,例如SELECT table_name || '.' || column_name || ' AS "' || table_name || '.' || column_name || '"'. 然而,双引号别名可能会导致额外的复杂性(区分大小写等);因此,我使用下划线字符将表名与别名中的列名分开,然后可以将别名视为常规列名。