How to fetch those records who appears in many records in many to many relationship in PostgreSQL?












1















I have the following three tables:



create table users(id int primary key, name varchar);
create table groups(id int primary key, name varchar);
create table user_groups(uid int references users(id), gid int references groups(id));


Following are the records in the respective tables:



insert into users values (1, 'John'), (2, 'Bob'), (3, 'Maria'), (4, 'Jin');

insert into groups values (1, 'Persons - A'), (2, 'Persons - B'),
(3, 'Persons - C'), (4, 'Persons - D'), (5, 'Pay - A'), (6, 'Pay - B'), (7, 'Pay - C');

insert into user_groups values (1, 1), (1, 2), (2, 1), (2, 4), (2, 6), (2, 7),
(3, 1), (3, 7), (4, 1), (4, 3);


Note: There are two types of groups, Persons and Pay



Now I want to find those users who have access to both types of groups (Persons and Pay), below is the desired output:



id        name       groups_user_has_access_to
2 Bob Persons - A, Persons - D, Pay - B, Pay - C
3 Maria Persons - A, Pay - C


The result should have only those users with their groups that have access to both types of groups.



Sorry for the bad English and appreciate your help in advance.










share|improve this question





























    1















    I have the following three tables:



    create table users(id int primary key, name varchar);
    create table groups(id int primary key, name varchar);
    create table user_groups(uid int references users(id), gid int references groups(id));


    Following are the records in the respective tables:



    insert into users values (1, 'John'), (2, 'Bob'), (3, 'Maria'), (4, 'Jin');

    insert into groups values (1, 'Persons - A'), (2, 'Persons - B'),
    (3, 'Persons - C'), (4, 'Persons - D'), (5, 'Pay - A'), (6, 'Pay - B'), (7, 'Pay - C');

    insert into user_groups values (1, 1), (1, 2), (2, 1), (2, 4), (2, 6), (2, 7),
    (3, 1), (3, 7), (4, 1), (4, 3);


    Note: There are two types of groups, Persons and Pay



    Now I want to find those users who have access to both types of groups (Persons and Pay), below is the desired output:



    id        name       groups_user_has_access_to
    2 Bob Persons - A, Persons - D, Pay - B, Pay - C
    3 Maria Persons - A, Pay - C


    The result should have only those users with their groups that have access to both types of groups.



    Sorry for the bad English and appreciate your help in advance.










    share|improve this question



























      1












      1








      1








      I have the following three tables:



      create table users(id int primary key, name varchar);
      create table groups(id int primary key, name varchar);
      create table user_groups(uid int references users(id), gid int references groups(id));


      Following are the records in the respective tables:



      insert into users values (1, 'John'), (2, 'Bob'), (3, 'Maria'), (4, 'Jin');

      insert into groups values (1, 'Persons - A'), (2, 'Persons - B'),
      (3, 'Persons - C'), (4, 'Persons - D'), (5, 'Pay - A'), (6, 'Pay - B'), (7, 'Pay - C');

      insert into user_groups values (1, 1), (1, 2), (2, 1), (2, 4), (2, 6), (2, 7),
      (3, 1), (3, 7), (4, 1), (4, 3);


      Note: There are two types of groups, Persons and Pay



      Now I want to find those users who have access to both types of groups (Persons and Pay), below is the desired output:



      id        name       groups_user_has_access_to
      2 Bob Persons - A, Persons - D, Pay - B, Pay - C
      3 Maria Persons - A, Pay - C


      The result should have only those users with their groups that have access to both types of groups.



      Sorry for the bad English and appreciate your help in advance.










      share|improve this question
















      I have the following three tables:



      create table users(id int primary key, name varchar);
      create table groups(id int primary key, name varchar);
      create table user_groups(uid int references users(id), gid int references groups(id));


      Following are the records in the respective tables:



      insert into users values (1, 'John'), (2, 'Bob'), (3, 'Maria'), (4, 'Jin');

      insert into groups values (1, 'Persons - A'), (2, 'Persons - B'),
      (3, 'Persons - C'), (4, 'Persons - D'), (5, 'Pay - A'), (6, 'Pay - B'), (7, 'Pay - C');

      insert into user_groups values (1, 1), (1, 2), (2, 1), (2, 4), (2, 6), (2, 7),
      (3, 1), (3, 7), (4, 1), (4, 3);


      Note: There are two types of groups, Persons and Pay



      Now I want to find those users who have access to both types of groups (Persons and Pay), below is the desired output:



      id        name       groups_user_has_access_to
      2 Bob Persons - A, Persons - D, Pay - B, Pay - C
      3 Maria Persons - A, Pay - C


      The result should have only those users with their groups that have access to both types of groups.



      Sorry for the bad English and appreciate your help in advance.







      postgresql many-to-many






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 8 hours ago







      Abdul Raheem Ghani

















      asked Jan 16 at 5:08









      Abdul Raheem GhaniAbdul Raheem Ghani

      158314




      158314






















          1 Answer
          1






          active

          oldest

          votes


















          1














          Here's my sample query for your question, the query could be slow depending on your table size



          SELECT t.uid, u.name, t.groups_user_has_access_to
          FROM (
          -- Each of GID, finding its big group (PERSON, PAY) --> called: group_type.
          -- Using distinct to remove duplicated element in group_type
          SELECT ug.uid,
          array_agg (distinct
          case when g.name like 'Person%' then 'Person'
          when g.name like 'Pay%' then 'Pay' end) as group_type,
          array_agg(g.name) as groups_user_has_access_to
          FROM user_groups ug
          JOIN groups g on ug.gid = g.id
          GROUP BY ug.uid
          )t
          JOIN users u on t.uid = u.id
          WHERE array_length(t.group_type, 1) > 1 -- Reject any UID which belong to 1 group.
          ORDER BY t.uid;


          I would suggest you to read the array functions in the query above.






          share|improve this answer

























            Your Answer








            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "182"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f227243%2fhow-to-fetch-those-records-who-appears-in-many-records-in-many-to-many-relations%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            Here's my sample query for your question, the query could be slow depending on your table size



            SELECT t.uid, u.name, t.groups_user_has_access_to
            FROM (
            -- Each of GID, finding its big group (PERSON, PAY) --> called: group_type.
            -- Using distinct to remove duplicated element in group_type
            SELECT ug.uid,
            array_agg (distinct
            case when g.name like 'Person%' then 'Person'
            when g.name like 'Pay%' then 'Pay' end) as group_type,
            array_agg(g.name) as groups_user_has_access_to
            FROM user_groups ug
            JOIN groups g on ug.gid = g.id
            GROUP BY ug.uid
            )t
            JOIN users u on t.uid = u.id
            WHERE array_length(t.group_type, 1) > 1 -- Reject any UID which belong to 1 group.
            ORDER BY t.uid;


            I would suggest you to read the array functions in the query above.






            share|improve this answer






























              1














              Here's my sample query for your question, the query could be slow depending on your table size



              SELECT t.uid, u.name, t.groups_user_has_access_to
              FROM (
              -- Each of GID, finding its big group (PERSON, PAY) --> called: group_type.
              -- Using distinct to remove duplicated element in group_type
              SELECT ug.uid,
              array_agg (distinct
              case when g.name like 'Person%' then 'Person'
              when g.name like 'Pay%' then 'Pay' end) as group_type,
              array_agg(g.name) as groups_user_has_access_to
              FROM user_groups ug
              JOIN groups g on ug.gid = g.id
              GROUP BY ug.uid
              )t
              JOIN users u on t.uid = u.id
              WHERE array_length(t.group_type, 1) > 1 -- Reject any UID which belong to 1 group.
              ORDER BY t.uid;


              I would suggest you to read the array functions in the query above.






              share|improve this answer




























                1












                1








                1







                Here's my sample query for your question, the query could be slow depending on your table size



                SELECT t.uid, u.name, t.groups_user_has_access_to
                FROM (
                -- Each of GID, finding its big group (PERSON, PAY) --> called: group_type.
                -- Using distinct to remove duplicated element in group_type
                SELECT ug.uid,
                array_agg (distinct
                case when g.name like 'Person%' then 'Person'
                when g.name like 'Pay%' then 'Pay' end) as group_type,
                array_agg(g.name) as groups_user_has_access_to
                FROM user_groups ug
                JOIN groups g on ug.gid = g.id
                GROUP BY ug.uid
                )t
                JOIN users u on t.uid = u.id
                WHERE array_length(t.group_type, 1) > 1 -- Reject any UID which belong to 1 group.
                ORDER BY t.uid;


                I would suggest you to read the array functions in the query above.






                share|improve this answer















                Here's my sample query for your question, the query could be slow depending on your table size



                SELECT t.uid, u.name, t.groups_user_has_access_to
                FROM (
                -- Each of GID, finding its big group (PERSON, PAY) --> called: group_type.
                -- Using distinct to remove duplicated element in group_type
                SELECT ug.uid,
                array_agg (distinct
                case when g.name like 'Person%' then 'Person'
                when g.name like 'Pay%' then 'Pay' end) as group_type,
                array_agg(g.name) as groups_user_has_access_to
                FROM user_groups ug
                JOIN groups g on ug.gid = g.id
                GROUP BY ug.uid
                )t
                JOIN users u on t.uid = u.id
                WHERE array_length(t.group_type, 1) > 1 -- Reject any UID which belong to 1 group.
                ORDER BY t.uid;


                I would suggest you to read the array functions in the query above.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jan 16 at 9:05

























                answered Jan 16 at 9:00









                Luan HuynhLuan Huynh

                90611227




                90611227






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Database Administrators Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f227243%2fhow-to-fetch-those-records-who-appears-in-many-records-in-many-to-many-relations%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    ف. موراي أبراهام

                    صرب

                    كأس إنترتوتو