PHP SQL - Retrieve shared values from a another table not as expected - php

I'm needing to retrieve shared values from a table based on a value from another table, but don't show duplicates.
Example of what tables I have...
Table - members
+-----------------+
| ID | NAME |
+-----------------+
| 1 | Bob |
| 2 | Jack |
| 3 | Jane |
| 4 | Bruce |
| 5 | Clark |
| 6 | Peter |
+-----------------+
Table - groups
+--------------------------------+
| ID | NAME | MANAGER_ID |
+--------------------------------+
| 1 | Group A | 1 | (Bob)
| 2 | Group B | 2 | (Jack)
| 3 | Group C | 1 | (Bob)
+--------------------------------+
Table - group_members
+--------------------------------+
| ID | GROUP_ID | MEMBER_ID |
+--------------------------------+
| 1 | 1 | 3 | (Group A - Jane)
| 2 | 1 | 4 | (Group A - Bruce)
| 3 | 1 | 5 | (Group A - Clark)
| 4 | 1 | 6 | (Group A - Peter)
| 5 | 2 | 3 | (Group B - Jane)
| 6 | 3 | 4 | (Group B - Bruce)
| 7 | 3 | 5 | (Group C - Clark)
+--------------------------------+
What I am needing
(Note: I'm using * in queries here to shorten code.)
If 'Bob' sees all his groups.
Look at 'group_members' table and show all members that belong to it...
$q = SELECT * FROM groups WHERE manager_id = $id;
$r = mysqli_query($dbc, $q);
while ($row = mysqli_fetch-assoc($r) {
$q2 = SELECT *, count(MEMBERS_ID) AS group_count FROM group_members LEFT JOIN members ON group_members.MEMBER_ID = members.id WHERE group_id = '$row[GROUP_ID]';
$r2 = mysqli_query($dbc, $q2);
while ($row2 = mysqli_fetch-assoc($r2) {
echo $row2['name'];
}
}
This shows me the list as expected.
+------------------------+
| NAME | GROUP COUNT |
+------------------------+
| Jane | 1 |
| Bruce | 1 |
| Clark | 1 |
| Peter | 1 |
| Bruce | 1 |
| Clark | 1 |
+------------------------+
I Add GROUP BY group_members.group_id to my 2nd query and that shows.
+------------------------+
| NAME | GROUP COUNT |
+------------------------+
| Jane | 1 |
| Bruce | 2 |
| Clark | 2 |
| Peter | 1 |
+------------------------+
Which is perfect... But here is the problem
if I add a WHERE members.name LIKE \'%clark%\' then it outputs...
+------------------------+
| NAME | GROUP COUNT |
+------------------------+
| | |
| | |
| Clark | 1 |
| | |
| | |
| Clark | 1 |
+------------------------+
It ignores GROUP BY and shows blank rows where other entries would show.
So with all that said. Does any one know why or a better way to do this please?
Been at it for a while now and would really appreciate any assistance.
EDITED:
Here's the full query with all the columns used:
$q = SELECT * FROM groups WHERE manager_id = $id;
$r = mysqli_query($dbc, $q);
while ($row = mysqli_fetch-assoc($r) {
$q2 = SELECT members.id) AS memid, members.first, members.last, members.comname, members.email, members.sector, (members.status) AS memstatus, (group_members.id) AS groupid, (group_members.member_id) AS memidgroup, group_members.group_id, COUNT(group_members.member_id) AS groupcount, member_roles.role FROM members LEFT JOIN group_members ON members.id = group_members.member_id LEFT JOIN member_roles ON members.role_id = member_roles.id WHERE group_id = '$row[GROUP_ID]' AND members.name LIKE '%clark%' GROUP BY group_members.group_id;
$r2 = mysqli_query($dbc, $q2);
while ($row2 = mysqli_fetch-assoc($r2) {
echo $row2['name'];
}
}

Your query or problem is not completely stated. One cannot guess or assume.
Post your last query as well as all queries dont worry about saving the space.
Those blank rows have data that why they are in the table.
Base on your explanation or your query, here is my simple answer
SELECT id,
(select groups.id from groups where groups.id = group_members.group_id )AS group_members_id,
(select groups.name from groups where groups.id = group_members.group_id )AS group_members_name,
(select members.id from members where members.id = group_members.member_id )AS members_id,
(select members.name from members where members.id = group_members.member_id )AS members_name,
count((select members.id from members where members.id = group_members.member_id ) )as members_id_count FROM group_members WHERE (select members.name from members where members.id = group_members.member_id ) LIKE '%clark%' group by members_id
As you mentioned
WHERE members.name LIKE \'%clark%\'
you were selecting data from the members table whereas you have to select the data from group_members table.

Related

How to check if 2 values IS NULL

I have these tables...
GROUP_MEMBERS
+---------------------------------+
| id | group_id | member_id |
+---------------------------------+
| 1 | 1 | 1 |
| 2 | 1 | 4 |
+---------------------------------+
MEMBERS
+-------------------------------------+
| id | first | last | role_id |
+-------------------------------------+
| 1 | Jack | Jones | 1 |
| 2 | Jane | Doe | 2 |
| 3 | Bob | Bee | 2 |
| 4 | Jen | Nee | 1 |
+-------------------------------------+
GROUPS
+-----------------+
| id | name |
+-----------------+
| 1 | group1 |
| 2 | group2 |
+-----------------+
As it is, I am using the following query...
SELECT
(members.id) AS memid,
members.first,
members.last,
members.role_id
FROM
members
LEFT JOIN group_members ON
members.id = group_members.member_id
WHERE
group_members.member_id IS NULL
GROUP BY
members.id;
This outputs the members (Jane and Bob) who are not in the 'GROUP_MEMBERS' table as it should, but what I am trying get working is if I am on and another group ($_GET['group_id']), how can I show all members that do not have rows that match group_id and member_id on the 'GROUP_MEMBERS' table...
i.e if group_id = '2' show all members
I have tried adding in WHERE clause... AND group_members.group_id IS NULL.. but it shows nothing then.
Does anyone have a query which would get the output I'm looking for?
Thanks
[EDITED]
Just to clarify...
If my url had 'group_id=1'
I should see:
Bob
Jane
If my url has 'group_id=2'
I should see:
Jack
Jane
Bob
Jen
So it only shows 'members' that do not exist( with the 'group_id' in the url) in the 'GROUP_MEMBERS' table
If I have understood the question correctly, you are looking for something like I have made on this fiddle:
DB Fiddle
The query I use is:
$sql = 'SELECT * FROM groups
RIGHT JOIN group_members ON groups.id = group_id
RIGHT JOIN members ON member_id = members.id
WHERE group_id <> ? OR group_id is NULL;'
$group_id = $_GET['group_id'];
$query = $mysqli->prepare($sql);
$query->bind_param('i', $group_id);
In short, this query will select from the groups table, ensuring that we will select every group in your database.
Then we will join the other two tables completely (using the RIGHT JOIN).
Finally, we are going to select every member that isn't the specified the one provided by the URL, or any member that is not in a group.
You can use a sub-query
how can I show all members that do not have rows that match 'group_id'
$group_id= $_GET['group_id'];
$q = "SELECT * FROM MEMBERS WHERE MEMBERS.id NOT IN(
SELECT member_id FROM GROUP_MEMBERS WHERE group_id='$group_id'
);";
Explanation
SELECT member_id FROM GROUP_MEMBERS WHERE group_id='$grID'
this will get all the members in this group by a given ID
then you select all members that are not among them.
SELECT * FROM MEMBERS WHERE MEMBERS.id NOT IN()
this one will give members data except the ids inside the brackets
the sub query will get the ids of members in a given group
no need for joining the three tables since you are using id of the group existing in GROUP_MEMBERS and linking the GROUP and MEMBERS
one side note
if you have a group name and what all users not in this group you then will need to use the GROUPS table
SELECT * FROM MEMBERS WHERE MEMBERS.id NOT IN(
SELECT member_id FROM GROUP_MEMBERS WHERE group_id = (
SELECT id from GROUPS WHERE name = '$Group_Name'
)
);
you may use WHERE group_id IN (...) it will work the same
This is a demonstration, I created same database with same data and tested the queries
+----+-------+-------+---------+
| id | first | last | role_id |
+----+-------+-------+---------+
| 1 | Jack | Jones | 1 |
| 2 | Jane | Doe | 2 |
| 3 | Bob | Bee | 2 |
| 4 | Jen | Nee | 2 |
+----+-------+-------+---------+
+----+--------+
| id | name |
+----+--------+
| 1 | group1 |
| 2 | group2 |
+----+--------+
+----+----------+-----------+
| id | group_id | member_id |
+----+----------+-----------+
| 1 | 1 | 1 |
| 2 | 1 | 4 |
+----+----------+-----------+
I run the sub-query as above and the results as expected,
MariaDB []> select * from members where id not in
(select member_id from group_members where group_id = 1);
+----+-------+------+---------+
| id | first | last | role_id |
+----+-------+------+---------+
| 2 | Jane | Doe | 2 |
| 3 | Bob | Bee | 2 |
+----+-------+------+---------+
similar for when you have group name
MariaDB []> select * from members where id not in
(select member_id from group_members where group_id =
(select id from groups where name='group1'));
+----+-------+------+---------+
| id | first | last | role_id |
+----+-------+------+---------+
| 2 | Jane | Doe | 2 |
| 3 | Bob | Bee | 2 |
+----+-------+------+---------+

How to SELECT 2 joined tables in one MySQL query?

I have 1 master_table and 2 sub_tables. I want the join the 3 columns together (but the problem is the 2 sub_tables do not have any column that share the same value) and then SELECT * based on 2 different columns from the 2 sub_tables.
I've searched and tried many ways of coding, but couldn't find a solution.
SELECT *
FROM (master INNER JOIN sub_1 ON master.id=sub_1.id WHERE sub_1.column_1 = 'Y')
AND (master INNER JOIN sub_2 ON master.id=sub_2.id WHERE sub_2.column_2 = 'Y')
ORDER BY master.id
++++++++++++++++++++++++++++++++++++++++++++++++++
* Finally, solved. See the solution at the bottom of this post. *
++++++++++++++++++++++++++++++++++++++++++++++++++
===========
Edit: explain more about my data, problem and MySQL code
I have 3 tables stored in MySQL as follow
Master_table: regist
------------------------------------------
| reg_no | firstname | lastname | submit |
------------------------------------------
| 1 | first_A | last_A | N |
| 2 | first_B | last_B | A |
| 3 | first_C | last_C | P |
| 4 | first_D | last_D | P |
| 5 | first_E | last_E | A |
| 6 | first_F | last_F | N |
| 7 | first_G | last_G | N |
| 8 | first_H | last_H | A |
------------------------------------------
Sub_1: sub_A Sub_2: sub_P
------------------------------ ------------------------------
| reg_no | A_title | reply_A | | reg_no | P_title | reply_P |
------------------------------ ------------------------------
| 2 | 222 | Y | | 3 | 333 | N |
| 5 | 555 | N | | 4 | 444 | Y |
| 8 | 888 | Y | ------------------------------
------------------------------
I want to create a query that gives result like this
----------------------------------------------------------------------------------
| reg_no | firstname | lastname | submit | A_title | reply_A | P_title | reply_P |
----------------------------------------------------------------------------------
| 2 | first_B | last_B | A | 222 | Y | | |
| 8 | first_H | last_H | A | 888 | Y | | |
| 4 | first_D | last_D | P | | | 444 | Y |
----------------------------------------------------------------------------------
or
-----------------------------------------------------------
| reg_no | firstname | lastname | submit | title | reply |
-----------------------------------------------------------
| 2 | first_B | last_B | A | 222 | Y |
| 8 | first_H | last_H | A | 888 | Y |
| 4 | first_D | last_D | P | 444 | Y |
-----------------------------------------------------------
$sql = "SELECT *
FROM (regist INNER JOIN sub_A ON regist.reg_no = sub_A.reg_no WHERE sub_A.reply_A = 'Y')
AND (regist INNER JOIN sub_P ON regist.reg_no = sub_P.reg_no WHERE sub_P.reply_P = 'Y')
ORDER BY regist.reg_no";
Expected outcome:
ECHO personal data of all registrants who got reply as 'Y'
if($row['submit']=="A") $title = $row['A_title'];
elseif($row['submit']=="P") $title = $row['P_title'];
$result = mysql_query($sql) or die(mysql_error());
while($row = mysql_fetch_array($result))
{
echo $row['reg_no']." / ".$row['firstname']." ".$row['lastname']." / ".$title."<br>";
}
Problem: my SELECT code resulted in error. The code from #GMB and #Rogue didn't error, but echo give nothing.
If it is not possible to code a query as I want, I will just modify the column names (sub_1.reply_A and sub_2.reply_P) to be the same and change the input code in other webpages. However, it would be best if there is a way because I don't know whether the 'reply' columns were used somewhere else.
========================
Solution: a little modification from #Rogue code
SELECT *
FROM master
LEFT OUTER JOIN sub_1
ON master.id=sub_1.id
LEFT OUTER JOIN sub_2
ON master.id=sub_2.id
WHERE sub_1.column_1 = 'Y'
OR sub_2.column_2 = 'Y'
ORDER BY master.id
Do you just want simple JOINs between these 3 tables ?
SELECT m.*, s1.*, s2.*
FROM master m
INNER JOIN sub_1 s1 ON m.id=s1.id AND s1.column_1 = 'Y'
INNER JOIN sub_2 s2 ON m.id=s2.id AND s2.column_2 = 'Y'
ORDER BY m.id;
If you have master records that may not exist in both sub tables, you can switch to LEFT JOIN to avoid filtering them out.
Guidelines :
typical syntax is SELECT ... FROM table1 INNER JOIN table2 ON ... INNER JOIN table3 ON...
better put all conditions related to a JOINed table in the ON clause of the join rather than in the WHERE clause
avoid SELECT * : be specific about the columns you want to select
use table aliases to make the query easier to read
You're a little off syntactically:
SELECT *
FROM master
LEFT OUTER JOIN sub_1
ON master.id=sub_1.id
LEFT OUTER JOIN sub_2
ON master.id=sub_2.id
WHERE sub_1.column_1 = 'Y'
AND sub_2.column_2 = 'Y'
ORDER BY master.id
Personally I would recommend not using SELECT * and only grabbing the data you will need. As for determining what join to use, I like to link to CodingHorror's blog post in these times.
Edit: swapped INNER to LEFT OUTER, per OP's update

mysql fetch data in where condition

I have 3 table now:
First is : member_username
+-------------+------------------+
| uid | username |
+-------------+------------------+
| 1 | theone |
| 2 | ohno |
| 3 | prayforpr |
+-------------+------------------+
Second is : member_data
+-------------+-------------------+-----------------+
| uid | talk | etc |
+-------------+-------------------+-----------------+
| 1 | talk1 | |
| 2 | talkeee | |
| 3 | iojdfnl | |
+---------------------------------------------------+
Third is : member_level
+-------------+-------------------+-----------------+
| uid | level | fid |
+-------------+-------------------+-----------------+
| 1 | 2 | 1 |
| 1 | 10 | 2 |
| 2 | 1 | 1 |
| 2 | 99 | 2 |
| 1 | 40 | 3 |
| 3 | 50 | 1 |
| 1 | 44 | 4 |
+---------------------------------------------------+
I would like to query data and display the only one uid when member_level is higher in when SUM member_level.level Where fid in 1,2,3.
my query now is like below, but this query is sum all the level including fid 4 also, how to specify only sum in fid 1,2,3? and how do I assign the SUM of member_level.level Where fid in 1,2,3 to $levelKingTotalLevel?
$levelKing = DB::query("SELECT t1.uid,t1.username,t2.talk FROM ".DB::table('member_level')." t3 JOIN ".DB::table('member_username')." t1 ON(t3.uid = t1.uid) JOIN ".DB::table('member_data')." t2 ON (t1.uid = t2.uid) GROUP BY t3.uid ORDER BY SUM(t3.level) DESC LIMIT 1");
while($rowlevelKing = DB::fetch($levelKing)) {
$levelKingTotalLevel = $rowlevelKing['???'];
$levelKingN = $rowlevelKing['username'];
$levelKingUID = $rowlevelKing['uid'];
$levelKingT = $rowlevelKing['talk'];
};
echo "The ".$levelKingN." total level is ".$levelKingTotalLevel." and he talk about ".$levelKingT;
Thank you.
To filter records having fid values as 1, 2 or 3, use IN statement in WHERE clause. Alias totalLevel in select statement will give you total level for a user.
SELECT t1.uid, t1.username, t2.talk, SUM(t3.level) AS totalLevel
FROM member_level t3
JOIN member_username t1
ON (t3.uid = t1.uid)
JOIN member_data t2
ON (t1.uid = t2.uid)
WHERE t3.fid IN (1,2,3)
GROUP BY t3.uid
ORDER BY totalLevel DESC
LIMIT 1

I want to display same column twice with different values mysql

select * from Teams;
| team_name | team_id |
| India | 1 |
| England | 2 |
| Germany | 3 |
| Japan | 4 |
select * from Matches;
| match_id | match_date | hometeam | awayteam | homescore | awayscore |
| 1 | 2014-06-24 | 1 | 2 | 3 | 0 |
| 2 | 2014-06-25 | 3 | 4 | 0 | 2 |
Matches-table hometeam and awayteam are foreign keys for Teams-table team_id
I want a select that displays the homescore and awayscore along with team_names
You have to join matches table with teams table like this:
SELECT th.team_name as team_home, m.homescore, ta.team_name as team_away, m.awayscore
FROM matches m
INNER JOIN teams th ON m.hometeam = th.team_id
INNER JOIN teams ta ON m.awayteam = ta.team_id
Here is SqlFiddle
Another one, with entire match data in one select...
select
m.*,
home.team_name as hometeam_name,
away.team_name as awayteam_name
from
matches m,
teams home,
teams away
where
home.team_id = m.hometeam
and
away.team_id = m.awayteam
;
see SQLFIDDLE

Combining results on a MySQL INNER JOIN into one PHP array

I have two tables that I would like to join into one, but not all the fields. I've used INNER JOIN with some success, but can't get the exact results I need. Essentially, when using PHP to return results, I would like the key to be the 'meta_key' value.
Below are the two tables I want to combine:
USERS
+--------+-----------------+------------------+----------------+
| ID | username | first_name | last_name |
+--------+-----------------+------------------+----------------+
| 2 | hthompson | Hunter | Thompson |
| 7 | coak | Carol | Oak |
| 8 | delk | Dannie | Elk |
| 9 | mride | Mark | Ride |
| 10 | kken | Kyle | Ken |
| 11 | glee | Ginny | Lee |
| 12 | nwatts | Naomi | Watts |
| 13 | jwong | Jin | Wong |
| 14 | syin | Shen | Yin |
+--------+-----------------+------------------+----------------+
USERS_META
+--------+--------+-----------------+------------------+
| ID | UID | meta_key | meta_value |
+--------+--------+-----------------+------------------+
| 1 | 2 | business_name | Company Inc. |
| 2 | 2 | city | New York |
| 3 | 2 | state | NY |
| 5 | 9 | city | Boston |
| 6 | 9 | state | MA |
| 7 | 11 | business_type | Printer |
| 8 | 8 | chamber_member | true |
| 9 | 2 | business_type | Design |
+--------+--------+-----------------+------------------+
Below is an example of what I'd like to return:
USERS
+--------+-----------------+------------+------------+------------------+
| ID | username | city | state | business_name |
+--------+-----------------+------------+------------+------------------+
| 2 | hthompson | New York | NY | Company Inc. |
+--------+-----------------+------------+------------+------------------+
OR
$user['ID'] = 2
$user['username'] = hthompson
$user['city'] = New York
$user['state'] = NY
$user['business_name'] = Company Inc.
The closest I've come is this:
$query = ("SELECT *
FROM users
INNER JOIN users_meta ON users.ID = users_meta.UID
WHERE
users_meta.meta_key = 'city' OR
users_meta.meta_key = 'state' OR
users_meta.meta_key = 'business_name'
");
However, doing such returns three results for each unique user ID, and I'm aiming to returning one with all the meta info specified. The primary purpose of this is so that I will be able to search using a keyword, which would apply to the USERS.first_name, USERS.first_name and USERS_META.business_name columns and then obviously return results in a table showing ID, Business Name, City, State, First & Last Name.
Thanks in advance!
You can try this:
SELECT
u.ID,
u.username,
m0.meta_value as city,
m1.meta_value as state,
m2.meta_value as business_name
FROM
users u,
users_meta m0,
users_meta m1,
users_meta m2
WHERE
u.ID = m0.UID
AND m0.meta_key = 'city'
AND u.ID = m1.UID
AND m1.meta_key = 'state'
AND u.ID = m2.UID
AND m2.meta_key = 'business'
As far as getting the information out I would just suggest joining the table together and using php to make the array. Something similar to this:
<?php
//if search is blank, returns all rows
$search = isset($_POST['search'])?mysql_real_escape_string($_POST['search']):'';
//query for all rows with meta key/values including extra
//rows from the join. extra rows will be taken out later.
$result = mysql_query(
"SELECT
U.ID,
U.USERNAME,
U.FIRST_NAME,
U.LAST_NAME,
UM.META_KEY,
UM.META_VALUE
FROM USERS U
JOIN USERS_META UM ON U.ID=UM.UID
WHERE
UM.META_KEY IN ('city', 'state', 'business_name')
AND U.FIRST_NAME LIKE '%{$search}%'");
//an empty array to put our results into
$out = array();
//loop through the rows
while($row=mysql_fetch_assoc($out)){
//check if the user id has been added already
if(!isset($out[$row['ID']])){
//if not, add it with generic information
$out[$row['ID']] = array(
'ID'=>$row['ID'],
'USERNAME'=>$row['USERNAME'],
'FIRST_NAME'=>$row['FIRST_NAME'],
'LAST_NAME'=>$row['LAST_NAME']);
}
//add the meta key and value
$out[$row['ID']][$row['META_KEY']] = $row['META_VALUE'];
}
//display
echo '<pre>'.print_r($out,1).'</pre>';
?>

Categories