Search code examples
sqldatabasepostgresqljoinsql-view

Creating Postgres View getting ERROR: column "id" specified more than once


SCENARIO:

I have this select statement that JOINs a bunch of tables together:

SELECT 
    e0.id, e0.name, e0.slug,
    e1.id, e1.edition, e1.url, e1.date, e1.event_id,
    v2.id, v2.title, v2.language, v2.description, v2.provider, v2.videoid, v2.image_url, v2.event_id, v2.edition_id,
    s3.id, s3.name, s3.twitter, s3.website
FROM 
    events AS e0 
LEFT OUTER JOIN 
    editions AS e1 ON e1.event_id = e0.id
LEFT OUTER JOIN 
    videos AS v2 ON v2.edition_id = e1.id
LEFT OUTER JOIN 
    videos_speakers AS v4 ON v4.video_id = v2.id
LEFT OUTER JOIN 
    speakers AS s3 ON v4.speaker_id = s3.id
ORDER BY 
    e1.date DESC;

I'd like to create a Postgres View. So wrote it out like this:

CREATE VIEW all_events 
AS
    SELECT 
        e0.id, e0.name, e0.slug,
        e1.id, e1.edition, e1.url, e1.date, e1.event_id,
        v2.id, v2.title, v2.language, v2.description, v2.provider, v2.videoid, v2.image_url, v2.event_id, v2.edition_id,
        s3.id, s3.name, s3.twitter, s3.website
    FROM 
        events AS e0 
    LEFT OUTER JOIN 
        editions AS e1 ON e1.event_id = e0.id
    LEFT OUTER JOIN 
        videos AS v2 ON v2.edition_id = e1.id
    LEFT OUTER JOIN 
        videos_speakers AS v4 ON v4.video_id = v2.id
    LEFT OUTER JOIN 
        speakers AS s3 ON v4.speaker_id = s3.id
    ORDER BY 
        e1.date DESC;

I keep getting this error:

ERROR: column "id" specified more than once

QUESTIONS:

  1. How do I fix this error? I would like to create a view called "all_events".
  2. Are Postgres View sort of like aliases in other languages?

New to Postgres, reading the docs but trying to understand the mental model here.


Solution

  • You have several column names that are the same. Even if you select e0.id the column is still name (only) id.

    But in the scope of a view (or table) each column name must be unique.

    You need to provide aliases for each duplicate column:

    CREATE VIEW all_events AS
    SELECT  e0.id as event_id, --<< here 
            e0.name as event_name, --<< here 
            e0.slug,
            e1.id as edition_id,  --<< here
            e1.edition, 
            e1.url, 
            e1.date, 
            e1.event_id as edition_event_id, --<< here
            v2.id as video_id,  --<< here
            v2.title, 
            v2.language, 
            v2.description, 
            v2.provider, 
            v2.videoid, 
            v2.image_url, 
            v2.event_id as video_event_id, --<< here 
            v2.edition_id as video_edition_id, --<< here
            s3.id as speaker_id,  --<< here
            s3.name as speaker_name, --<< here 
            s3.twitter, 
            s3.website
    FROM events AS e0 
      LEFT OUTER JOIN editions AS e1 ON e1.event_id = e0.id
      LEFT OUTER JOIN videos AS v2 ON v2.edition_id = e1.id
      LEFT OUTER JOIN videos_speakers AS v4 ON v4.video_id = v2.id
      LEFT OUTER JOIN speakers AS s3 ON v4.speaker_id = s3.id;
    

    Although Postgres allows it, I highly recommend to not create a view with an ORDER BY statement. If you ever sort the results of that view by a different column, Postgres will sort the data twice.