Thanks for reading.
I'm trying to learn inner join and join. My aim is to comparing that if the user created the community is also marked as an admin in the CommunityMembers table (I'm not sure if INNER JOIN achieves this) and take all other community information from Community table related to CommunityID (this is possible with inner join as I understand).
I have two tables called Community and CommunityMembers.
the structure is for Community(it has other data such as date, contents etc...):
CommunityID - Slug - CreatedByUser
1 - video - 2
2 - funny - 2
3 - picture - 4
for CommunityMembers
CmID - UserID - Slug - Power
1 - 2 - video - admin
2 - 2 - funny - admin
3 - 4 - picture - admin
my php code: ( $_SESSION['UserID'] is 2 )
<?php
$sql = $dbc->prepare(" SELECT cm.*, com.*
FROM Community com
INNER JOIN CommunityMembers cm ON cm.UserID = com.CreatedByUser
WHERE cm.UserID = '" . $_SESSION['UserID'] . "'");
$sql->execute();
if($sql->rowCount()){
echo $sql->rowCount();
while($data = $sql->fetch()){
$output .= $data['Slug'] .'<br />';
}
echo $output;
}else{
$_ERROR = "no record";
}
?>
echo $output; prints
video
video
video
funny
funny
funny
and echo $sql->rowcount(); prints
6
Could you please help with this? Why is this printing same thing 3 times? and is my solution right to check if is user created the community is marked as admin in the CommunityMembers or do I need to check it?
Thanks.
Try this
$sql = $dbc->prepare("
SELECT cm.*, com.*
FROM Community com
INNER JOIN CommunityMembers cm ON cm.UserID = com.CreatedByUser
WHERE cm.UserID = '" . $_SESSION['UserID'] . "'
GROUP BY com.CreatedByUser
");
$sql = $dbc->prepare(" SELECT DISTINCT cm.*, com.*
FROM Community com
INNER JOIN CommunityMembers cm ON cm.UserID = com.CreatedByUser
WHERE cm.UserID = '" . $_SESSION['UserID'] . "'");
SELECT DISTINCT
http://dev.mysql.com/doc/refman/5.0/en/distinct-optimization.html
If all you need to know if its admin, don't bring all fields from CommunityMembers. Try this
$sql = $dbc->prepare(" SELECT DISTINCT cm.Power, com.*
FROM Community com
LEFT JOIN CommunityMembers cm ON cm.UseriID=com.CreaterByUser
WHERE cm.UserID = '" . $_SESSION['UserID'] . "'");
Didn't test it, but this should work even without DISTINCT.
If you select the 2 tables result SELECT cm.*, com.* it will return all differents couples so try to select only specifics fields you need.
PS : What is the full result, I mean not only the field slug ?
Related
I am requesting your advice about the following:
I have two tables:
Customers and Orders.
I am printing the data of customers inside a table using a while loop:
$sql = "SELECT * FROM wccrm_customers where status = '1' order by date desc";
$result = mysql_query($sql, $db);
while ($daten = mysql_fetch_array($result)) { ?>
echo $daten[id];
echo $daten[name] . ' ' . $daten[vorname];
echo $daten[email];
echo $daten[telefon];
} ?>
Now I try to add a new field in this list: Purchased YES/NO. As we have more customers then buyers, we want to show whether someone has bought or not:
The Connection between this two tables is the first/lastname in both tables!
So if customer.name = orders.name and customer.firstname = orders.firstname I want to echo "YES" if not then "NO"
I tried with a JOIN, but here I just get the results who are in both table:
SELECT *
FROM wccrm_customers AS k
INNER JOIN wccrm_orders AS o
ON o.namee = k.name AND o.firstname = k.firstname
but I need to have all of the customers and the ones who are in both lists marked...
Is this possible? If yes: How can I achieve this?
Thank's for your advice!
Kind regards,
Stefan
This has nothing to do with PHP, or with while loops; you just need to form your join properly:
SELECT DISTINCT
`k`.*,
`o`.`namee` IS NOT NULL AS `Purchased`
FROM `wccrm_customers` AS `k`
LEFT JOIN `wccrm_orders` AS `o`
ON
`o`.`namee` = `k`.`name`
AND `o`.`firstname` = `k`.`firstname`
Read more about the different join types: http://www.sql-join.com/sql-join-types/
(images courtesy of that site, which also contains an example and discussion of almost exactly what you're trying to do!)
By the way, you must have missed the massive red warning banner in the manual about using the deprecated (now removed) mysql_* functions. You should stop doing that! Use MySQLi or PDO instead.
a shorter one
SELECT DISTINCT k.*, IF(o.namee IS NULL, 'no', 'yes') purchased
FROM
wccrm_customers AS k
LEFT JOIN wccrm_orders AS o USING (namee,firstname)
I have three tables, "food","member" and "member_food". I'm trying to make an update user page where a collection of tags are prepopulated by the data in "member_food".
I have debugged the ID sending from the previous page which allows me to select the entry I wish to query, ID:4.
$query = "SELECT * FROM `food` left join `member_food` on food.entityid = member_food.food_id WHERE member_id = '$id'";
//Breakfast
$breakfastresult1 = $mysqli->query($query);
echo '<select name="breakfast1">';
while($BreakfastData1 = mysqli_fetch_array($breakfastresult1, MYSQL_ASSOC))
{
echo '<p><option value="' . htmlspecialchars($BreakfastData1['member_food.food_id']) . '">'
. htmlspecialchars($BreakfastData1['member_food.food_name'])
. '</option>'
. '</p>';
}
echo '</select>';
However, the select fields appear to be empty. I think it's not pulling the correct values from my leftjoin table.
Here is an example of my member_food table:
food table:
edit this, first you have a typo (space missing in left + join) second you need to tell from which of the table member_id belong
$query = "SELECT * FROM `food` as f left join `member_food` as mf on f.entityid = mf.food_id WHERE mf.member_id = '$id'";
You can use this to plan your joins correctly. And, as Abdul pointed out, typos are bad ;)
I am currently refactoring a legacy application and converting piece by piece over to zend framework 1.12.
I am scratching my head as to how to convert this over to zend db, is there a way that this can be done in one query?
Right now I see that it fetches a list of folders first and then runs an additional query per folder...
Running this as one query will improve performance, right?
$folders_query = DB::Query("select * from contacts_folders order by sort_order, name");
while($folders = DB::FetchArray($folders_query)){
$counts_total = DB::QueryOne("SELECT count(cm.messages_id) AS total
FROM contacts_basics cb, contacts_messages cm
WHERE cb.contacts_id = cm.contacts_id
AND cm.folders_id = '" . $folders['folders_id'] . "'
AND cm.status = '1'
AND cm.mark = '0'");
if ($counts_total >0){
$folders_name = '<strong>' . $folders['name'] . ' (' . $counts_total . ')</strong>';
} else {
$folders_name = $folders['name'];
}
echo '<li><a href="messages.php?fID=' . $folders['folders_id'] . '">';
echo $folders_name;
echo '</a></li>';
}
Yes, you can do both in the same query
SELECT cf.*, count(cm.messages_id) AS total
FROM contacts_folders cf left outer join
contacts_messages cm
on cf.id = cm.folders_id and
cm.status = '1' AND cm.mark = '0' left outer join
contacts_basics cb
on cb.contacts_id = cm.contacts_id
group by cf.folders_id
order by cf.sort_order, cf.name;
This uses a left outer join to be sure that you get all folders, even if there are no messages (which is how the original code works). Because of the left outer join, the conditions need to be moved into on clauses.
It also fetches all the information from the folders as well as the total. If there are no messages, then it should return 0 for that folder.
There was a minor bug in Gordon's answer but I figured it out thanks to him.
I changed
contacts_basics cb left outer join
To:
left outer join contacts_basics cb
The following code works as expected:
public function getMenuCounts(){
$raw = "SELECT cf.*, count(cm.messages_id) AS total
FROM contacts_folders cf left outer join
contacts_messages cm
on cf.folders_id = cm.folders_id and
cm.status = '1' AND cm.mark = '0'
left outer join contacts_basics cb
on cb.contacts_id = cm.contacts_id
group by cf.folders_id
order by cf.sort_order, cf.name;";
$db = Zend_Db_Table::getDefaultAdapter();
$stmt = $db->query($raw);
return $stmt->fetchAll();
}
i am having trouble creating a single mysql query for what i am trying to do here.
first off, i will show you the table structures and fields of the tables i am using for this particular query:
users:
- id
- name
- photo_name
- photo_ext
user_attacks:
- id
- level
user_news_feed:
- id
- id_user
- id_status
- id_attack
- id_profile
- id_wall
- the_date
user_status:
- id
- status
user_wall:
- id
- id_user
- id_poster
- post
whenever the user posts an attack, or status update, updates their profile, or posts on someones wall, it inserts the relevant data into its respective table and also inserts a new row into the user_news_feed table.
now, what i want to do is select the last 10 news feed items from the database. these news feed items need to grab relevant data from other tables as long as their value is not 0. so if the news feed is for a status update, the id_status would be the id of the status update in the user_status table, and the "status" would be the data needing to be selected via a left join. hope that makes sense.
heres my first mysql query:
$sql = mysql_query("select n.id_user, n.id_status, n.id_attack, n.id_profile, n.id_wall, n.the_date, u.id, u.name, u.photo_name, u.photo_ext, s.status
from `user_news_feed` as n
left join `users` u on (u.id = n.id_user)
left join `user_status` s on (s.id = n.id_status)
where n.id_user='".$_GET['id']."'
order by n.id desc
limit 10
");
now this works great, except for 1 problem. as you can see the user_wall table contains the id's for 2 different users. id_user is the user id the post is being made for, and id_poster is the user id of the person making that wall post. if the user makes a wall post on his/her own wall, it is inserted into the database as a status update into the user_status table instead.
so i have a conditional statement within the while loop for the first query, which has another sql query within it. here is the whole code for the while loop and second sql query:
while ($row = mysql_fetch_assoc($sql))
{
if ($row['id_wall'] != 0)
{
$sql_u = mysql_query("select u.id, u.name, u.photo_name, u.photo_ext, w.post
from `user_wall` as w
left join `users` u on (u.id = w.id_poster)
where w.id='".$row['id_wall']."'
");
while ($row_u = mysql_fetch_assoc($sql_u))
{
$row['photo_name'] = $row_u['photo_name'];
$row['photo_ext'] = $row_u['photo_ext'];
$row['id_user'] = $row_u['id'];
$row['name'] = $row_u['name'];
$content = $row_u['post'];
}
}
else
{
if ($row['id_status'] != 0)
$content = $row['status'];
else if ($row['id_attack'] != 0)
$content = '<i>Had an attack</i>';
else if ($row['id_profile'] != 0)
$content = '<i>Updated profile</i>';
}
echo '<li'.(($count == $total_count) ? ' class="last"' : '').'>';
echo '<img src="images/profile/'.$row['photo_name'].'_thumb.'.$row['photo_ext'].'" alt="" />';
echo '<div class="content">';
echo '<b>'.$row['name'].'</b>';
echo '<span>'.$content.'</span>';
echo '<small>'.date('F j, Y \a\t g:ia', $row['the_date']).'</small>';
echo '</div>';
echo '<div style="clear: both;"></div>';
echo '</li>';
}
i hope what i am trying to do here makes sense. so basically i want to have both sql queries ($sql, and $sql_u) combined into a single query so i do not have to query the database every single time when the user_news_feed item is a wall post.
any help would be greatly appreciated and i apologise if this is confusing.
SELECT n.id_user, n.id_status, n.id_attack, n.id_profile, n.id_wall, n.the_date,
u.id, u.name, u.photo_name, u.photo_ext, s.status,
w.id AS wall_user_id, w.name AS wall_user_name,
w.photo_name AS wall_user_photo_name,
w.photo_ext AS wall_user_photo_ext,
w.post
FROM user_news_feed AS n
LEFT JOIN users AS u ON (u.id = n.id_user)
LEFT JOIN user_status s ON (s.id = n.id_status)
LEFT JOIN (SELECT a.id AS id_wall, b.id, b.name, b.photo_name, b.photo_ext, a.post
FROM user_wall AS a
LEFT JOIN users AS b ON (b.id = a.id_poster)
) AS w ON w.id_wall = n.id_wall
WHERE n.id_user = ?
ORDER BY n.id desc
LIMIT 10
The '?' is a placeholder where you can provide the value of $_GET['id'].
Basically, this adds an extra outer join, to the main query (and some extra columns, which will be NULL if the news feed event is not a wall posting), but the outer join is itself the result of an outer join.
Back again ;)
Anyway, forget about merging the queries in my opinion.
What you should do instead is to do the first query, loop through all the results and store all "id_wall"s in a separate array... then rather than doing a separate query per "id_wall" you do this:
$wallids = array();
while ($row = mysql_fetch_assoc($sql))
{
$wallids[] = $row['id_wall'];
// also store the row wherever you want
}
$sql_u = mysql_query("select u.id, u.name, u.photo_name, u.photo_ext, w.post
from `user_wall` as w
left join `users` u on (u.id = w.id_poster)
where w.id IN ('".implode(',', $wallids) ."')
");
$wallids being an array with all the "id_wall"s. So now you have a total of 2 queries.
i have small problem in my sql query
my tables
/* threads
thread_id/thread_title/thread_content
1 / any post title / welcome to my post
relations
cate_id/thread_id
1 / 1
2 / 1
categories
category_id/category_name
1 / some_cate
2 / second_cate
*/
My sql query
$q = mysql_query("SELECT t.*,c.*, GROUP_CONCAT(r.cate_id SEPARATOR ' ') as cate_id
FROM threads as t
LEFT JOIN relations as r on r.thread_id = t.thread_id
LEFT JOIN categories as c on c.category_id = r.cate_id
GROUP BY r.thread_id
");
php code
while($thread = mysql_fetch_array($q)){
echo 'Post title is: ' . $thread['thread_title'] . '<br />'; // work fine
echo 'Post content is: ' . $thread['thread_content'] . '<br />'; //work fine
echo 'Categories id is : ' . $thread['cate_id'] . '/' . '<br />'; // cate_id of relations table work fine
echo 'Categories names is : ' . $thread['category_name'] . '/'; // category name of categories table don't work fine
echo '-------End of first POOOOOOOOOOOST--------';
}
OUTPUT
/*
any post title
welcome to my post
1/2
some_cate/
-------End of first POOOOOOOOOOOST-------
*/
Now my problem is!
There is small problem in query
there is two categories id (1 and 2)
should be there is two categories name!
some_cate / second_cate
but it display only one! though it display two categories id!
categories names does not repeat
but the categories id is repeat! and working fine
##Doug Kress
i tryid your code but there is problem in your code with mysql_fetch_array
i got duplication of posts!
any post title
welcome to my post
some_cate/
any post title
welcome to my post
second_cate/
i am using CONCAT and GROUP BY to avoid this problem
The problem is actually in the GROuP BY - you're telling it to group by r.thread_id - based on your example, there's only one thread_id (1), so it will only return one record.
I'm guessing you don't need the GROUP BY or the GROUP_CONCAt at all.
SELECT t.thread_title, t.thread_content, r.cate, c.category_name
FROM threads as t
LEFT JOIN relations as r on r.thread_id = t.thread_id
LEFT JOIN categories as c on c.category_id = r.cate_id
It's usually best to specify all of the fields that you're going to use. Otherwise, it's unnecessary work for MySQL and for PHP, and it doesn't make your intent very clear.
I don't know the data, but based on your sample, you could change the LEFT join to an INNER join.
You must add GROUP_CONCAT(c.category_name, ' ') as category_name at your SELECT statement
If you will meet problem with same column name then just rename category_name to something else.