Query to get subjects of interest for all User Y where Y shares >=3 interests with a User X











up vote
1
down vote

favorite












These are two tables from a part of supposed Twitter like database where users can follow other users. The User.name field is unique.



mysql> select uID, name from User;
+-----+-------------------+
| uID | name |
+-----+-------------------+
| 1 | Alice |
| 2 | Bob |
| 5 | Iron Maiden |
| 4 | Judas Priest |
| 6 | Lesser Known Band |
| 3 | Metallica |
+-----+-------------------+
6 rows in set (0.00 sec)

mysql> select * from Follower;
+-----------+------------+
| subjectID | observerID |
+-----------+------------+
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
| 3 | 2 |
| 4 | 2 |
| 5 | 2 |
+-----------+------------+
7 rows in set (0.00 sec)

mysql> call newFollowSuggestionsForName('Bob');
+-------------------+
| name |
+-------------------+
| Lesser Known Band |
+-------------------+
1 row in set (0.00 sec)


I want to make an operation that will suggest for a user X a list of users they may be interested in following. I thought one heuristic could be to show X for all y who user y follows where X and y follow at least 3 of the same Users. Below is the SQL I came up with to do this. My question is if it could be done more efficiently or nicer in some other ways.



DELIMITER //
CREATE PROCEDURE newFollowSuggestionsForName(IN in_name CHAR(60))
BEGIN

DECLARE xuid INT;
SET xuid = (select uID from User where name=in_name);

select name
from User, (select subjectID
from follower
where observerID in (
select observerID
from Follower
where observerID<>xuid and subjectID in (select subjectID from Follower where observerID=xuid)
group by observerID
having count(*)>=3
)
) as T
where uID = T.subjectID and not exists (select * from Follower where subjectID=T.subjectID and observerID=xuid);

END //
DELIMITER ;









share|improve this question






















  • Why do you input in_name as Char. You must be having its integer ID value also. My suggestion is to use that instead. It will be more performant. Moreoever, what happens if there are two users with same name(s) ?
    – Madhur Bhaiya
    Nov 11 at 8:22












  • Also, do you have access to latest version of MySQL (version 8.0.2 and above) ?
    – Madhur Bhaiya
    Nov 11 at 8:26















up vote
1
down vote

favorite












These are two tables from a part of supposed Twitter like database where users can follow other users. The User.name field is unique.



mysql> select uID, name from User;
+-----+-------------------+
| uID | name |
+-----+-------------------+
| 1 | Alice |
| 2 | Bob |
| 5 | Iron Maiden |
| 4 | Judas Priest |
| 6 | Lesser Known Band |
| 3 | Metallica |
+-----+-------------------+
6 rows in set (0.00 sec)

mysql> select * from Follower;
+-----------+------------+
| subjectID | observerID |
+-----------+------------+
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
| 3 | 2 |
| 4 | 2 |
| 5 | 2 |
+-----------+------------+
7 rows in set (0.00 sec)

mysql> call newFollowSuggestionsForName('Bob');
+-------------------+
| name |
+-------------------+
| Lesser Known Band |
+-------------------+
1 row in set (0.00 sec)


I want to make an operation that will suggest for a user X a list of users they may be interested in following. I thought one heuristic could be to show X for all y who user y follows where X and y follow at least 3 of the same Users. Below is the SQL I came up with to do this. My question is if it could be done more efficiently or nicer in some other ways.



DELIMITER //
CREATE PROCEDURE newFollowSuggestionsForName(IN in_name CHAR(60))
BEGIN

DECLARE xuid INT;
SET xuid = (select uID from User where name=in_name);

select name
from User, (select subjectID
from follower
where observerID in (
select observerID
from Follower
where observerID<>xuid and subjectID in (select subjectID from Follower where observerID=xuid)
group by observerID
having count(*)>=3
)
) as T
where uID = T.subjectID and not exists (select * from Follower where subjectID=T.subjectID and observerID=xuid);

END //
DELIMITER ;









share|improve this question






















  • Why do you input in_name as Char. You must be having its integer ID value also. My suggestion is to use that instead. It will be more performant. Moreoever, what happens if there are two users with same name(s) ?
    – Madhur Bhaiya
    Nov 11 at 8:22












  • Also, do you have access to latest version of MySQL (version 8.0.2 and above) ?
    – Madhur Bhaiya
    Nov 11 at 8:26













up vote
1
down vote

favorite









up vote
1
down vote

favorite











These are two tables from a part of supposed Twitter like database where users can follow other users. The User.name field is unique.



mysql> select uID, name from User;
+-----+-------------------+
| uID | name |
+-----+-------------------+
| 1 | Alice |
| 2 | Bob |
| 5 | Iron Maiden |
| 4 | Judas Priest |
| 6 | Lesser Known Band |
| 3 | Metallica |
+-----+-------------------+
6 rows in set (0.00 sec)

mysql> select * from Follower;
+-----------+------------+
| subjectID | observerID |
+-----------+------------+
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
| 3 | 2 |
| 4 | 2 |
| 5 | 2 |
+-----------+------------+
7 rows in set (0.00 sec)

mysql> call newFollowSuggestionsForName('Bob');
+-------------------+
| name |
+-------------------+
| Lesser Known Band |
+-------------------+
1 row in set (0.00 sec)


I want to make an operation that will suggest for a user X a list of users they may be interested in following. I thought one heuristic could be to show X for all y who user y follows where X and y follow at least 3 of the same Users. Below is the SQL I came up with to do this. My question is if it could be done more efficiently or nicer in some other ways.



DELIMITER //
CREATE PROCEDURE newFollowSuggestionsForName(IN in_name CHAR(60))
BEGIN

DECLARE xuid INT;
SET xuid = (select uID from User where name=in_name);

select name
from User, (select subjectID
from follower
where observerID in (
select observerID
from Follower
where observerID<>xuid and subjectID in (select subjectID from Follower where observerID=xuid)
group by observerID
having count(*)>=3
)
) as T
where uID = T.subjectID and not exists (select * from Follower where subjectID=T.subjectID and observerID=xuid);

END //
DELIMITER ;









share|improve this question













These are two tables from a part of supposed Twitter like database where users can follow other users. The User.name field is unique.



mysql> select uID, name from User;
+-----+-------------------+
| uID | name |
+-----+-------------------+
| 1 | Alice |
| 2 | Bob |
| 5 | Iron Maiden |
| 4 | Judas Priest |
| 6 | Lesser Known Band |
| 3 | Metallica |
+-----+-------------------+
6 rows in set (0.00 sec)

mysql> select * from Follower;
+-----------+------------+
| subjectID | observerID |
+-----------+------------+
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
| 3 | 2 |
| 4 | 2 |
| 5 | 2 |
+-----------+------------+
7 rows in set (0.00 sec)

mysql> call newFollowSuggestionsForName('Bob');
+-------------------+
| name |
+-------------------+
| Lesser Known Band |
+-------------------+
1 row in set (0.00 sec)


I want to make an operation that will suggest for a user X a list of users they may be interested in following. I thought one heuristic could be to show X for all y who user y follows where X and y follow at least 3 of the same Users. Below is the SQL I came up with to do this. My question is if it could be done more efficiently or nicer in some other ways.



DELIMITER //
CREATE PROCEDURE newFollowSuggestionsForName(IN in_name CHAR(60))
BEGIN

DECLARE xuid INT;
SET xuid = (select uID from User where name=in_name);

select name
from User, (select subjectID
from follower
where observerID in (
select observerID
from Follower
where observerID<>xuid and subjectID in (select subjectID from Follower where observerID=xuid)
group by observerID
having count(*)>=3
)
) as T
where uID = T.subjectID and not exists (select * from Follower where subjectID=T.subjectID and observerID=xuid);

END //
DELIMITER ;






mysql sql






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 10 at 23:52









bagel_lord

29113




29113












  • Why do you input in_name as Char. You must be having its integer ID value also. My suggestion is to use that instead. It will be more performant. Moreoever, what happens if there are two users with same name(s) ?
    – Madhur Bhaiya
    Nov 11 at 8:22












  • Also, do you have access to latest version of MySQL (version 8.0.2 and above) ?
    – Madhur Bhaiya
    Nov 11 at 8:26


















  • Why do you input in_name as Char. You must be having its integer ID value also. My suggestion is to use that instead. It will be more performant. Moreoever, what happens if there are two users with same name(s) ?
    – Madhur Bhaiya
    Nov 11 at 8:22












  • Also, do you have access to latest version of MySQL (version 8.0.2 and above) ?
    – Madhur Bhaiya
    Nov 11 at 8:26
















Why do you input in_name as Char. You must be having its integer ID value also. My suggestion is to use that instead. It will be more performant. Moreoever, what happens if there are two users with same name(s) ?
– Madhur Bhaiya
Nov 11 at 8:22






Why do you input in_name as Char. You must be having its integer ID value also. My suggestion is to use that instead. It will be more performant. Moreoever, what happens if there are two users with same name(s) ?
– Madhur Bhaiya
Nov 11 at 8:22














Also, do you have access to latest version of MySQL (version 8.0.2 and above) ?
– Madhur Bhaiya
Nov 11 at 8:26




Also, do you have access to latest version of MySQL (version 8.0.2 and above) ?
– Madhur Bhaiya
Nov 11 at 8:26












2 Answers
2






active

oldest

votes

















up vote
0
down vote













Consider the following refactored SQL code (untested without data) for use in stored procedure.



select u.`name`
from `User` u
inner join
(select subf.observerID, subf.subjectID
from follower subf
where subf.observerID <> xuid
) f
on u.UID = f.subjectID
inner join
(select f1.observerID
from follower f1
inner join follower f2
on f1.subjectID = f2.subjectID
and f1.observerID <> xuid
and f2.observerID = xuid
group by f1.observerID
having count(*) >= 3
) o
on f.observerID = o.observerID





share|improve this answer




























    up vote
    0
    down vote













    I think the basic query starts as getting all "observers" who share three "subjects" with a given observer:



    select f.observerid
    from followers f join
    followers f2
    on f.subjectid = f2.subjectid and
    f2.observerid = 2
    group by f.observerid
    having count(*) = 3;


    The rest of the query is just joining in the names to fit into your paradigm of using names for references rather than ids.






    share|improve this answer





















      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      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',
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      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%2fstackoverflow.com%2fquestions%2f53244573%2fquery-to-get-subjects-of-interest-for-all-user-y-where-y-shares-3-interests-wi%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      0
      down vote













      Consider the following refactored SQL code (untested without data) for use in stored procedure.



      select u.`name`
      from `User` u
      inner join
      (select subf.observerID, subf.subjectID
      from follower subf
      where subf.observerID <> xuid
      ) f
      on u.UID = f.subjectID
      inner join
      (select f1.observerID
      from follower f1
      inner join follower f2
      on f1.subjectID = f2.subjectID
      and f1.observerID <> xuid
      and f2.observerID = xuid
      group by f1.observerID
      having count(*) >= 3
      ) o
      on f.observerID = o.observerID





      share|improve this answer

























        up vote
        0
        down vote













        Consider the following refactored SQL code (untested without data) for use in stored procedure.



        select u.`name`
        from `User` u
        inner join
        (select subf.observerID, subf.subjectID
        from follower subf
        where subf.observerID <> xuid
        ) f
        on u.UID = f.subjectID
        inner join
        (select f1.observerID
        from follower f1
        inner join follower f2
        on f1.subjectID = f2.subjectID
        and f1.observerID <> xuid
        and f2.observerID = xuid
        group by f1.observerID
        having count(*) >= 3
        ) o
        on f.observerID = o.observerID





        share|improve this answer























          up vote
          0
          down vote










          up vote
          0
          down vote









          Consider the following refactored SQL code (untested without data) for use in stored procedure.



          select u.`name`
          from `User` u
          inner join
          (select subf.observerID, subf.subjectID
          from follower subf
          where subf.observerID <> xuid
          ) f
          on u.UID = f.subjectID
          inner join
          (select f1.observerID
          from follower f1
          inner join follower f2
          on f1.subjectID = f2.subjectID
          and f1.observerID <> xuid
          and f2.observerID = xuid
          group by f1.observerID
          having count(*) >= 3
          ) o
          on f.observerID = o.observerID





          share|improve this answer












          Consider the following refactored SQL code (untested without data) for use in stored procedure.



          select u.`name`
          from `User` u
          inner join
          (select subf.observerID, subf.subjectID
          from follower subf
          where subf.observerID <> xuid
          ) f
          on u.UID = f.subjectID
          inner join
          (select f1.observerID
          from follower f1
          inner join follower f2
          on f1.subjectID = f2.subjectID
          and f1.observerID <> xuid
          and f2.observerID = xuid
          group by f1.observerID
          having count(*) >= 3
          ) o
          on f.observerID = o.observerID






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 11 at 0:33









          Parfait

          48.2k84067




          48.2k84067
























              up vote
              0
              down vote













              I think the basic query starts as getting all "observers" who share three "subjects" with a given observer:



              select f.observerid
              from followers f join
              followers f2
              on f.subjectid = f2.subjectid and
              f2.observerid = 2
              group by f.observerid
              having count(*) = 3;


              The rest of the query is just joining in the names to fit into your paradigm of using names for references rather than ids.






              share|improve this answer

























                up vote
                0
                down vote













                I think the basic query starts as getting all "observers" who share three "subjects" with a given observer:



                select f.observerid
                from followers f join
                followers f2
                on f.subjectid = f2.subjectid and
                f2.observerid = 2
                group by f.observerid
                having count(*) = 3;


                The rest of the query is just joining in the names to fit into your paradigm of using names for references rather than ids.






                share|improve this answer























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  I think the basic query starts as getting all "observers" who share three "subjects" with a given observer:



                  select f.observerid
                  from followers f join
                  followers f2
                  on f.subjectid = f2.subjectid and
                  f2.observerid = 2
                  group by f.observerid
                  having count(*) = 3;


                  The rest of the query is just joining in the names to fit into your paradigm of using names for references rather than ids.






                  share|improve this answer












                  I think the basic query starts as getting all "observers" who share three "subjects" with a given observer:



                  select f.observerid
                  from followers f join
                  followers f2
                  on f.subjectid = f2.subjectid and
                  f2.observerid = 2
                  group by f.observerid
                  having count(*) = 3;


                  The rest of the query is just joining in the names to fit into your paradigm of using names for references rather than ids.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 11 at 12:32









                  Gordon Linoff

                  746k33285390




                  746k33285390






























                       

                      draft saved


                      draft discarded



















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244573%2fquery-to-get-subjects-of-interest-for-all-user-y-where-y-shares-3-interests-wi%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

                      Florida Star v. B. J. F.

                      Danny Elfman

                      Lugert, Oklahoma