Query between 3 tables with MySQL

0

I'm trying to make a query and add the values of two tables to the result so I can bring the inflationary I need

tables matches and blocked are related to users using the id's

The query I am trying to make is the following:

SELECT u.*, m.*
FROM users u, matches m
WHERE NOT EXISTS (
SELECT idblock
FROM blocked b
WHERE b.idBlock = u.id AND b.idBlocked = 9) AND u.id <> 9

and the result brings it as I need but it repeats many times, I tried to do it with a where exists but it did not work for me

this is the relationship that the tables have

What I try to bring in my query is all the information of id and the fields idMatch and% idMatched as long as accepted = 0 in the table of matches but as long as the id User% does not exist in idBlocked

  

RELATIONSHIP BETWEEN TABLES

the table of users is the primary table for consequent

in the table matches idMatch y idMatched have a FK to id of the table users as shown in the image

and in the blocked idBlock y idBlocked table have FK a id of users

Both tables have a ratio of 1 to many

I repeat the intention of my query again:

I want to bring all the user information to show it on the screen but I want to know if you already have a match to show a button, but in case there is no match show another button but I also want to know if the user id the blocked table has not been entered

ex. if user 1 blocks user 3 will not appear on screen but all others if

Relationship of if's between tables

@ A.Cedano as you mention, the match and blocked tables are relations between users, I really do not know how to explain what I want to do.

but in my head my intention is to take all the records of the users table after making a comparison in the match table, that is, if in the match table the idMatch user is = 9 and idMatched = 3 in the view will show a button, otherwise another button will be displayed

then I want to make another comparison where one user has not blocked another is to say if idBlock = 3 and idBlocked = 9, the user with id 3 will not be shown on screen for user 9.

and so at the end say "ok, the result brought all users of the users table but id 9 has a match with id 7, then I will show this button but id 3 blocking id 9, then I will not show this user "

But all that I want to do in a single query so you can show all the results on screen

    
asked by cesg.dav 13.07.2018 в 18:51
source

2 answers

2

I have tried to reproduce your problem based on real data and I have not found an optimal way to obtain the desired result.

If I understand correctly, it is about managing relationships between users.

The matches table would serve to know which users have requested friendship to which users. The accepted column would indicate if the friend request is accepted 1 or not accepted 0 .

The blocked table would serve to indicate who has blocked whom.

There are several problems in that design. I found a way to get the results you wanted, but it was not entirely satisfactory for just one reason: in the table matches the user can participate say as sender or as receiver em> of the friend request. In that case, check that the user we are looking for is sender or as receiver knocked down my supposed solution.

It seems to me that your data design can be thought of better. Also, you may not have to handle only the locks. What if you have to handle things like pending requests? What if you need to know who blocked whom or if they have blocked each other?

Then I propose this solution: create in the table matches a column that will be in charge of managing all the possible states of the relationship , namely:

  • friends : both have accepted the request
  • Receiver's pending sender : that is, so-and-so sent a friend request to Mengano, but he has not responded
  • receiver pending issuer : that is, mengano sent request to so and so, but he has not responded
  • so-and-so blocked to mengano
  • mengano blocked so-and-so
  • they blocked each other : that is, the friendship relationship ended in tragedy):

In your design you can implement a numerical convention (see comment before the% CREATE TABLE in the DEMO below) that expresses each state of the relationship or you can use ENUM .. That's the least of it.

By doing so, through this query you will get for example all the friends of the user 1 :

SELECT 
    ue.user_id id_emisor, 
    ur.user_id id_receptor
FROM matches_20180713 m
    LEFT JOIN users_20180713 ue ON ue.user_id=m.match_emisor
    LEFT JOIN users_20180713 ur ON m.match_receptor=ur.user_id
WHERE 
    m.match_emisor=1 OR m.match_receptor=1 AND m.match_status=1;

The result would be something like this:

id_emisor   id_receptor
    1            2
    4            1

Shows that the user 1 is friend of the users 2 and 4 . And it also shows that he asked for friendship at 2 and that the 4 asked him for friendship. Clear. Suppose you are asked for statistics in that sense, what your boss tells you: to see, I want a query to know, of the friends of 1 , how many did he ask for friendship and how many asked for it . With this design you have it completely solved.

Now, suppose you want to show user blocking situations 1 . You execute this query:

SELECT 
    ue.user_id id_emisor, 
    ur.user_id id_receptor,
    m.match_status
FROM matches_20180713 m
    LEFT JOIN users_20180713 ue ON ue.user_id=m.match_emisor
    LEFT JOIN users_20180713 ur ON m.match_receptor=ur.user_id
WHERE 
    (m.match_emisor=1 OR m.match_receptor=1) AND m.match_status>3;

In our column match_status I have previously agreed that the blocking states are from 4 , that's why the WHERE ... m.match_status>3 . The query will yield data like this:

id_emisor   id_receptor      match_status
    5             1               4
    1             7               6

We can read then that the user 5 asked the user friendship 1 and then block it (this is what the 4 represents in our numerical state convention). We also see that the user 1 asked the user% friendship 7 in a golden age but that relationship ended in a mutual block ... the golden years are over :(

This is my proposal for the solution of this so intricate problem. Maybe there are better solutions. It's a matter of trying and staying with the one that suits you best.

  

If you want to do a test on the data that I used to   reproduce the problem, you can see this DEMO EN   REXTESTER .

NOTE: I have given more descriptive names to the columns, so as not to get lost in the code and know the data I am dealing with. That's why the column names differ from yours. You can change that or leave it as you have it, at your choice. Anyway, it is convenient that the code is as understandable as possible, and using more descriptive names helps a lot.

I hope it serves you.

    
answered by 13.07.2018 в 23:14
0

Add in WHERE the condition that relates the two users and matches tables:

SELECT u.*, m.* fROM users u, matches m
WHERE NOT EXISTS (
SELECT idblock
FROM blocked b
WHERE b.idBlock = u.id AND b.idBlocked = 9) AND u.id <> 9 
      AND u.id = m.id
    
answered by 13.07.2018 в 19:16