Home > OS >  Why does my PostgreSQL query not work as expected?
Why does my PostgreSQL query not work as expected?

Time:08-31

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.

CodePudding user response:

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

CodePudding user response:

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
  • Related