skip to Main Content

I currently have two tables called calendars and events in my PostgreSQL database which are joined on calendars.uuid = events.calendar_id.

At present, a person can have more than one calendar in the calendars table, however I need to change this so the person_id has a unique constraint, and hence they should only be able to have one entry moving forward.

I therefore need to identify only the person(s) which currently have more than one calendar and all the associated records from the events table i.e. person_id = 4

calendars:

uuid | person_id
-----+---------------
   1 | 1
   2 | 2
   3 | 3
   4 | 4
   5 | 4
   6 | 4
   7 | 5
   8 | 5

events:

uuid | calendar_id | event_id
-----+-----------------------
   1 | 1           | 4728
   2 | 1           | 8942
   3 | 1           | 7842
   4 | 2           | 9784
   5 | 3           | 9852
   6 | 3           | 1298
   7 | 4           | 4983
   8 | 5           | 4892
   9 | 5           | 8522

My query is as follows, however this is not working, and as i’m fairly new to SQL/PSQL I’m struggling to figure this one out:

SELECT
    calendars.uuid,
    calendars.person_id,
    events.uuid,
    events.calendar_id,
    events.event_id
FROM
    events
    INNER JOIN (
        SELECT
            person_id,
            count(*)
        FROM
            calendars
        GROUP BY
            person_id
        HAVING
            count(*) > 1) AS calendars ON calendars.uuid = events.calendar_id

Any help would be much appreciated.

2

Answers


  1. You can join events and calendar then put the person_id in the where clause.

        SELECT 
                calendars.uuid,
                calendars.person_id,
                events.uuid,
                events.calendar_id,
                events.event_id 
        FROM 
            calendars  
        INNER JOIN events 
                ON events.calendar_id = calendars.uuid
        WHERE calendars.person_id in (
           SELECT
               person_id 
            FROM
               calendars
            GROUP BY
               person_id
            HAVING
                count(*) > 1 )
        
    
    
    uuid    person_id   uuid    calendar_id event_id
    4       4            7        4             4983
    5       4            8        5             4892
    5       4            9        5             8522
    
    Login or Signup to reply.
  2. I find it helps to structure your query such that you segregate the parts that are most restrictive first. So I would use a cte to restrict the persons to those wanted and then include the cte as an inner join to a standard query. Something like this:

    WITH cte as 
        (SELECT person_id
            FROM
                calendars
            GROUP BY
                person_id
            HAVING
                count(*) > 1)
    SELECT
        calendars.uuid,
        calendars.person_id,
        events.uuid,
        events.calendar_id,
        events.event_id
    FROM
        events
        INNER JOIN calendars ON calendars.uuid = events.calendar_id
        INNER JOIN cte ON cte.person_id = calendars.person_id
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search