how do I join multiple tables with foreign key constraints - php

I am a newbie to mysql, and originally I was going to create an enum datatype for my table but I found this question Create enum in SQL Server, and used it as a reference as that is what I needed. However when I tried to grab the data using the following sql statement it failed:
$sql = "
SELECT users.userID
, users.firstName
, users.lastName
, membersrank.rank
, memberstyle.style
FROM users
JOIN membersrank
ON membersrank.rankID = memberships.rankID
JOIN memberstyle
ON memberstyle.styleID = memberships.styleID
JOIN memberships
ON users.userID = memberships.userID
";
The prepare statement failed when I ran it. I assumed something is wrong with the sql statement.
$stmt = mysqli_stmt_init($conn);
if(!mysqli_stmt_prepare($stmt, $sql)) {
header("location: /index.php?error=stmtFailed");
exit();
}
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
These two tables below are the "user_rank" table referenced from the link.
Table: membersrank Table: memberstyle
| rankID | rank | | styleID | style |
| -------- | -------- | | -------- | ------------ |
| 0 | Guest | | 0 | N/A |
| 1 | Member | | 1 | Casual |
| 2 | Admin | | 2 | Competitive |
Table: memberships (is it the table, 'users', from the link)
| membershipID | userID | rankID | styleID |
| ------------ | -------- | -------- | -------- |
| 0 | 1 | 1 | 1 |
| 1 | 2 | 2 | 1 |
| 2 | 3 | 1 | 0 |
Result im trying to achieve:
| userID | firstName | lastName | rank | style |
| ------------ | ---------- | -------- | -------- | -------- |
| 0 | John | Doe | Member | Casual |
| 1 | Jane | Doe | Admin | Casual |
| 2 | Joe | Smith | Member | N/A |
How do I go about this and what is the proper sql statement?
(if need the unlisted table 'users' is required as info then is as you see in the my result table without the rank and style columns.)
Thanks in advance!

Related

How can I grab all possible results based on values in an SQL table when dealing with user permissions?

I have 5 tables, and only 4 of which are needed to grab the results I want. These tables are:
--------------
| Roles |
--------------
| ID | NAME |
--------------
| 1 | Admin |
--------------
| 2 | User |
--------------
-------------
| USERS |
-------------
| ID | NAME |
-------------
| 1 | Dan |
-------------
| 2 | Dave |
-------------
| 3 | Mike |
-------------
--------------------------------
| navigation |
--------------------------------
| ID | navlinks |
--------------------------------
| 1 | Home |
--------------------------------
| 2 | Admin Page |
--------------------------------
Table used for assigning a users role
--------------------------
| user_roles |
--------------------------
| ID | user_id | role_id |
--------------------------
| 1 | 1 | 1 |
--------------------------
| 2 | 2 | 2 |
--------------------------
| 3 | 3 | 1 |
--------------------------
Table used for assigning allowed user_roles to each navigation navlink
----------------------------------
| navigation_roles |
----------------------------------
| ID | navigation_id | user_role |
----------------------------------
| 1 | 1 | 1 |
----------------------------------
| 2 | 1 | 2 |
----------------------------------
| 3 | 2 | 1 |
----------------------------------
I want to be able to grab the user.name column and the navigation.navigation_name column that each user is allowed access to.
Dan and Dave should be shown the Admin and Home link, while Mike should only see Home. But my solution only shows both the Admin and Home for Dave only and Dan only has the Home link when he should also be shown the Admin link.
select users.name, navigation.navlinks FROM users
LEFT JOIN user_roles on users.id = user_roles.user_id
LEFT JOIN navigation_roles ON navigation_roles.role_id = user_roles.role_id
RIGHT JOIN navigation on navigation.id = navigation_roles.navigation_id;
So the above shows me:
----------------
| Dan | Home |
----------------
| Dave | Home |
----------------
| Mike | Home |
----------------
| Dave | Admin |
----------------
When it should be showing me:
----------------
| Dan | Home |
----------------
| Dave | Home |
----------------
| Mike | Home |
----------------
| Dave | Admin |
----------------
| Dan | Admin |
----------------
Problem was with the role_id values in the navigation_roles table.

Fetching all rows from a table where id repeats

+------+---------+----------+
| id | uid | assessors|
+------+---------+----------+
| 1 | 1 | Volvo |
| 2 | 2 | kenitra |
| 3 | 3 | rabat |
| 4 | 3 | Fahad |
| 5 | 3 | John |
+------+---------+----------+
I want to fetch the data on the base of uid because i use a Inner join to fetch data from other table now i want to fetch and show all assesors on uid but i get this output
+---------+----------+
| uid | assessors|
| 1 | Volvo |
| 2 | kenitra |
| 3 | rabat |
Desired Output is:
+---------+----------+
| uid | assessors|
| 1 | Volvo |
| 2 | kenitra |
| 3 | rabat |
| 3 | Fahad |
| 3 | John |
my query is =
SELECT * FROM lego_activity_answers WHERE uid = $studentid;
$studentid comes from another table
If you want to get all data in the lego_activity table except for id, simply select the individual fields you want, instead of querying *
SELECT uid, assessors FROM lego_activity_answers WHERE uid = $studentid;
SELECT DISTINCT uid ,assessors FROM lego_activity_answers where uid=$studentid;
( this may not perform well at all in large tables )

Cross database multiple records with join in MySQL

In this case each person can be assigned to an unlimited number of companies. One of these assigned companies should always be the person's main company. As you can see in the SQL query which I have posted the ID of the person's main organization is stored in the column "main_company_id" in the "person" table.
I have database Internal on server 192.168.0.1 with Person_Company Table as given
+----+-----------+------------+------------+
| id | person_id | company_id | created_at |
+----+-----------+------------+------------+
| 1 | 1005 | 2589 | 00:00:00 |
| 2 | 1006 | 2590 | 00:00:00 |
| 3 | 1007 | 2591 | 00:00:00 |
+----+-----------+------------+------------+
Person Table is as given
+------+-------+---------+-----------------+-----------------+
| id | name | phone | main_company_id | ref_id |
+------+-------+---------+-----------------+-----------------+
| 1005 | John | 0123456 | 2590 | 273722702297768 |
| 1006 | Doe | 7894560 | 2591 | 955413080598021 |
| 1007 | Smith | 9517530 | 2589 | 164283934074454 |
+------+-------+---------+-----------------+-----------------+
Company Table is as given
+------+-----------+---------+-----------------+
| id | name | vat | ref_id |
+------+-----------+---------+-----------------+
| 2589 | Company A | 0123456 | 540603005841231 |
| 2590 | Company B | 7894560 | 725472422399397 |
| 2591 | Company C | 9517530 | 367043795528136 |
+------+-----------+---------+-----------------+
Now there is another database External on the same server 192.168.0.1 with External_Person tables as given:
+----+-----------------+-------+----------------------+--------+
| id | ref_id | name | internal_primary_key | gender |
+----+-----------------+-------+----------------------+--------+
| 1 | 273722702297768 | John | ABC123456 | male |
| 2 | 955413080598021 | Doe | BCD456789 | female |
| 3 | 164283934074454 | Smith | DEF789456 | male |
+----+-----------------+-------+----------------------+--------+
And another table on this External database is External_Company
+----+-----------------+-----------+----------------------+
| id | ref_id | name | internal_primary_key |
+----+-----------------+-----------+----------------------+
| 1 | 540603005841231 | Company A | XX4123456 |
| 2 | 725472422399397 | Company B | XX5456789 |
| 3 | 367043795528136 | Company C | XX6789456 |
+----+-----------------+-----------+----------------------+
What I want to achieve is like this result:
+----+------------+-------------+------------------+
| id | person_key | company_key | main_company_key |
+----+------------+-------------+------------------+
| 1 | ABC123456 | XX4123456 | XX5456789 |
| 2 | BCD456789 | XX5456789 | XX6789456 |
| 3 | DEF789456 | XX6789456 | XX4123456 |
+----+------------+-------------+------------------+
I have already achieved two columns through this statement:
SELECT EEP.internal_primary_key as Person_Key, EEC.internal_primary_key as Company_Key
FROM Internal.Person_Company as IPC
JOIN Internal.Person as IP on IP.id = IPC.person_id
JOIN Internal.Company as IC on IC.id = IPC.company_id
JOIN External.External_Person as EEP on IP.ref_id = EEP.ref_id
JOIN External.External_Company as EEC on IC.ref_id = EEC.ref_id
WHERE IPC.person_id = 1005;
And this has the output like this result:
+----+------------+-------------+
| id | person_key | company_key |
+----+------------+-------------+
| 1 | ABC123456 | XX4123456 |
| 2 | BCD456789 | XX5456789 |
| 3 | DEF789456 | XX6789456 |
+----+------------+-------------+
How can I get the main company's internal_primary_key of the person in this given scenario? How can I amend my this existing query to achieve the desired result which I have mentioned above?
Does this work for you? You have a lot of good work, it seems all you would need is add the EEC.internal_primary_key as main_company_key code to your select statement.
SELECT EEP.internal_primary_key as person_Key, EEC.internal_primary_key as company_Key, EEC.internal_primary_key as main_company_key
FROM Internal.Person_Company as IPC
JOIN Internal.Person as IP on IP.id = IPC.person_id
JOIN Internal.Company as IC on IC.id = IPC.company_id
JOIN External.External_Person as EEP on IP.ref_id = EEP.ref_id
JOIN External.External_Company as EEC on IC.ref_id = EEC.ref_id
WHERE IPC.person_id = 1005;
I have done this successfully after doing some research upon databases
SELECT EEP.internal_primary_key as Person_Key, EEC.internal_primary_key as Company_Key, MEEC.internal_primary_key as Main_Company_Key
FROM Internal.Person_Company as IPC
JOIN Internal.Person as IP on IP.id = IPC.person_id
JOIN Internal.Company as IC on IC.id = IPC.company_id
JOIN External.External_Person as EEP on IP.ref_id = EEP.ref_id
JOIN External.External_Company as EEC on IC.ref_id = EEC.ref_id
JOIN Internal.Company as MIC on MIC.id = IP.main_company_id
JOIN External.External_Company as MEEC on MIC.ref_id = MEEC.ref_id
WHERE IPC.person_id = 1005;
And now this results as I wanted:
+----+------------+-------------+------------------+
| id | person_key | company_key | main_company_key |
+----+------------+-------------+------------------+
| 1 | ABC123456 | XX4123456 | XX5456789 |
| 2 | BCD456789 | XX5456789 | XX6789456 |
| 3 | DEF789456 | XX6789456 | XX4123456 |
+----+------------+-------------+------------------+

Loop through every value of string

I get form db field (organisations.paths)the following strings:
/1/2/3/4
Each number is the id of organisation's name from this db table:
+----+-------------+----------+----------+----------------------+
| id | frameworkid | path | parentid | fullname |
+----+-------------+----------+----------+----------------------+
| 1 | 1 | /1 | 0 | NYC University |
| 2 | 1 | /2 | 0 | Board of directors |
| 3 | 1 | /1/2/3 | 1 | Math faculty |
| 4 | 1 | /1/2/3/4 | 3 | Statistic department |
| 5 | 1 | /1/2/3/5 | 2 | Linguist department |
+----+-------------+----------+----------+----------------------+
Then I have the description table for each organisation:
+----+----------+---------+----------------+
| id | data | fieldid | organisationid |
+----+----------+---------+----------------+
| 1 | HQ | 1 | 1 |
| 2 | advisory | 1 | 2 |
| 3 | advisory | 1 | 3 |
| 4 | bottom | 1 | 4 |
| 5 | advisory | 1 | 5 |
+----+----------+---------+----------------+
How to join the both description table and main table and loop only through organisations, which have HQ or advisory in their description? So it becomes:
NYC University, Board of directors, Math faculty (Statistic department-won't be shown, as it is with description bottom)
You need to use explode, IN and join Function of PHP and mysql.
$var = "/1/2/3/4";
$in = join(" , ", explode("/", ltrim($var, '/')));
$sql = "SELECT `dt`.`fullname` FROM `db_table` dt
LEFT JOIN `organization` o
ON `o`.`organisationid` = `dt`.`id`
WHERE `o`.`id` IN ($in) AND (`o`.`data` = 'HQ' OR `o`.`data` = 'advisory')";
Make a loop to get the names and show them as you want.

SQL PHP - match records from one table to another based on several columns

I have 2 tables:
tbl1:
+-------+-------+
| p_id | f_id |
+-------+-------+
| 1 | 2 |
| 1 | 4 |
| 2 | 1 |
| 3 | 4 |
| 4 | 1 |
| 4 | 3 |
+-------+-------+
tbl2:
+-------+-------+-------+
| u_id | fname | lname |
+-------+-------+-------+
| 1 | adam | smith |
| 2 | jon | jones |
| 3 | sean | dent |
| 4 | jack | scott |
+-------+-------+-------+
my logged in id (php) is:
$user->id // this returns '3'
I need to return each u_id in tbl2 for each p_id in tbl1 that does NOT have my $user->id (3 in this example) in it's corresponding f_id. For example, 4 should not be returned because it has a 3 in one of it's f_id's. I hope this makes sense!!! Many thanks..
I think this query should work for you.
SELECT u_id FROM tbl2
WHERE u_id NOT IN
(SELECT p_id FROM tbl1
where f_id = $user);
You will need to build the query in PHP so that it boils down to the above query in SQL.

Categories