SQL LEFT JOIN without duplicating same row values - php

I was wondering if someone can help me with my problem that is as follows:
I want to pull once posts.text and uids which belongs to that posts.text but when I execute the code below it does this: eg. there are 4 uids that belongs to the post so I get the posts.text four times instead of once.
$query = mysqli_query($con,
"SELECT posts.text, relationships.uidb
FROM posts
LEFT JOIN relationships
ON posts.uid=relationships.uida
LIMIT 10");
if(mysqli_num_rows($query) > 0){
while($row = mysqli_fetch_assoc($query)){
echo $row['text']." ".$row['uidb']."<br>";
}
}
I would really appreciate any help.
Thanks is advance.
Peter
Update:
Desired output would be like this:
postsArray[0]->text = //post text
postsArray[1]->text = //another post text
postsArray[0]->uids[0] = //approved uid for first post
postsArray[0]->uids[1] = //another approved uid for first post
now it outputs this:
text 10
text 15
text 12
and I want this:
text 10, 15, 12

One way is to use Mysql's GROUP_CONCAT which provides comma separated values list for each group i.e (p.uid)
$query = mysqli_query($con,
"SELECT p.text, GROUP_CONCAT(r.uidb SEPARATOR ', ') uidbs
FROM posts p
LEFT JOIN relationships r
ON p.uid=r.uida
GROUP BY p.uid
LIMIT 10");
if (mysqli_num_rows($query) > 0) {
while ($row = mysqli_fetch_assoc($query)) {
echo $row['text'].' '.$row['uidbs'];
/*$uidbs= explode($row['uidbs'],',');
foreach ($uidbs as $key => $val) {
echo $val.' ';
}*/
echo '</br>';
}
}
GROUP_CONCAT
According to docs The result is truncated to the maximum length that
is given by the group_concat_max_len system variable, which has a
default value of 1024. The value can be set higher, although the
effective maximum length of the return value is constrained by the
value of max_allowed_packet.

Maybe this might work for you:
$query = mysqli_query($con,
"SELECT posts.text, relationships.uidb
FROM posts
LEFT JOIN relationships
ON posts.uid=relationships.uida
GROUP BY posts.uid
LIMIT 10");
if(mysqli_num_rows($query) > 0){
while($row = mysqli_fetch_assoc($query)){
echo $row['text']." ".$row['uidb']."<br>";
}
}

SELECT posts.text, relationships.uidb
FROM posts
LEFT JOIN relationships
ON posts.uid=relationships.uida
GROUP BY posts.primary_key_of_your_post
LIMIT 10

You should call 2 queries. In your first query, call the text, and then call uids.
You should not write complex queries because this will make your business more complex and you will not maintain your code in future.

Related

SELECT a value multiple time in SQL

I have a code in PHP where I want to display multiple times values, and so, even if these values are the same between them. My code is simple :
$sql = "SELECT photo from table WHERE username IN ('1','2','2') ORDER BY id DESC ";
$res = array();
$result = mysqli_query($con,$sql);
while($row = mysqli_fetch_array($result)){
array_push($res, $row['photo']);
}
echo json_encode($res);
But this code only display (in json) an array of two values (because the values of photo of the username 2 are the same).
What I want to achieve is to make an array with the exact same number of values of the number of username I defined WHERE username IN ('1','2','2') (so here, 3 values).
I hope you understood me, thanks for helping me !
I think what you're after is to list even the duplicates in the end result. As your SQL will only retrieve the unique items, the idea would be to include the username in the SQL result set. Then use the original list of user names ($userNames) and add in the photo for each of them.
I've used mysqli_fetch_all() to simplify the process of fetching all of the data, then used array_column() to make the username the key for the photos.
$userNames = array(1,2,2);
$sql = "SELECT username, photo
from table
WHERE username IN ('".implode("','", $userNames)."')
ORDER BY id DESC ";
$res = array();
$result = mysqli_query($con,$sql);
$photos = mysqli_fetch_all($result, MYSQLI_ASSOC);
$photos = array_column($photos, "photo", "username");
foreach ( $userNames as $user ) {
if ( isset($photos[$user])) {
$res[] = $photos[$user];
}
else {
$res[] = '';
}
}
echo json_encode($res);
You would use left join:
select t.photo
from (select '1' as username union all select '2' union all select '3'
) u left join
table t
on t.username = u.username
order by t.id desc;
Note this will return rows, even when the user name does not exist. If you want to filter those rows, remove the left so you are doing an inner join.

php loop start over when num_rows==0

I'm trying to write a php code to select form tables:
books
images
Some books does not have an image, so I want to skip it and select another book.
I have wrote this code but it does not work with me perfectly.
Now I'm getting only 5 records! it must be 6 as I limited in the book select query.
$slider_sql = "select * from books limit 6";
$slider_result = $conn->query($slider_sql);
while($slider_row = $slider_result->fetch_assoc()) {
extract($slider_row);
$img_sql = "SELECT big_img FROM images WHERE book_id = '$id'";
$img_rs = $conn->query($img_sql);
$img_row = $img_rs->fetch_assoc();
if ($img_rs->num_rows == 0)
continue; //--> here I want to start while again to select another book.
echo $book_name.'<br>';
echo $img_row['big_img'].'<br>';
}
Thanks for your help and time!
Instead of having a sub-query in a loop (which is nearly ALWAYS a bad idea!), use a JOIN instead, which simplifies it to one query instead of two. Then set a condition that big_img should not be empty. This guarantees that you will only find rows where there's an image matching the book. LIMIT will still only ensure the return of 6 rows. <> in MySQL is the same as !=.
$slider_sql = "SELECT b.book_name, i.big_img
FROM books b
JOIN images i
ON i.book_id=b.id
WHERE i.big_img <> ''
LIMIT 6";
$result = $conn->query($slider_sql);
while ($row = $result->fetch_assoc()) {
echo $row['book_name'].'<br>';
echo $row['big_img'].'<br>';
}
MySQL JOIN

Counting the number of times each variable appears in table

Basically, I am seeking to know if there is a better way to accomplish this specific task.
Basically, what happens is I query the db for a list of "project needs" -- These are each uniquer and only appear once.
Then, I search another table to find out how many members have the required "skills - which are directly correlated to the project needs".
I accomplished exactly what I was trying to do by running a second query and then inserting them into an array like this:
function countEachSkill(){
$return = array();
$query = "SELECT DISTINCT SKILL_ID, SKILL_NAME FROM PROJECT_NEEDS";
$result = mysql_query($query) or die(mysql_error());
$num_rows = mysql_num_rows($result);
while($row = mysql_fetch_assoc($result)){
$query = "SELECT COUNT(*) as COUNT FROM MEMBER_SKILLS WHERE SKILL_ID = '".$row['NEED_ID']."'";
$cResult = mysql_query($query);
$cRow = mysql_fetch_assoc($cResult);
$return[$row['SKILL_ID']]['Count'] = $cRow['COUNT'];
$return[$row['SKILL_ID']]['Name'] = $row['SKILL_NAME'];
}
arsort($return);
return $return;
}
But I feel like there has to be a better way (perhaps using some kind of join?) that would return this in a result set to avoid using the array.
Thanks in advance.
PS. I know mysql_ is depreciated. It is not my choice on which to use.
SELECT P.SKILL_ID, P.SKILL_NAME, COUNT(M.SKILL_ID) as COUNT FROM PROJECT_NEEDS P INNER JOIN MEMBER_SKILLS M
ON P.SKILL_ID=M.SKILL_ID
GROUP BY P.SKILL_ID, P.SKILL_NAME
I've adjusted Nriddens answer to accomodate for the select distinct, Im under the belief that his adjustment would be ok given SKILL_ID is a primary key
function countEachSkill(){
$return = array();
$query = "
SELECT
COUNT(*) AS COUNT,
PROJECT_NEEDS.SKILL_NAME,
PROJECT_NEEDS.SKILL_ID
FROM
(SELECT DISTINCT
SKILL_ID, SKILL_NAME
FROM
PROJECT_NEEDS) AS PROJECT_NEEDS
INNER JOIN
MEMBER_SKILLS
ON
MEMBER_SKILLS.SKILL_ID = PROJECT_NEEDS.SKILL_ID
GROUP BY PROJECT_NEEDS.SKILL_ID";
$result = mysql_query($query) or die(mysql_error());
$num_rows = mysql_num_rows($result);
while($row = mysql_fetch_assoc($result)){
$return[$row['SKILL_ID']]['Count'] = $row['COUNT'];
$return[$row['SKILL_ID']]['Name'] = $row['SKILL_NAME'];
}
arsort($return);
return $return;
I am subquerying on the select distinct because I dont believe you have a dedicated skills table with an auto inc primary key, if that was there I wouldn't be using a subquery.
Can you test this query
select project_needs.*,count(members_skills.*) as count from project_needs
inner join members_skills
on members_skills.skill_id=project_needs.skill_id Group by project_needs.skill_name, project_needs.skill_id

MySQL select from multiple identical tables and display results randomly with php

Hello I would like to query multiple identical tables in my db which has different prefixes and than display the results randomly but somehow I need to track the origin of the item and I couldn't figure out how
I do the query like this because I don't have access to information_schema
$query = "SHOW TABLES FROM mydb WHERE RIGHT( tables_in_mydb, 5 ) = 'table'";
$res = mysql_query($query);
$num = mysql_num_rows($res);
while($row = mysql_fetch_row($res)) {
$numbers = explode('_', $row[0]);
if($num > 0) {
$q = "SELECT `this`, `that`, `something` FROM ".$numbers[0]."_idetinticaltables"; // :)
$r = mysql_query($q);
while($c = mysql_fetch_array($r)) {
/*display the results randomly with an identifier where the come from*/
}
}
}
You could use ORDER BY RAND() to randomly sort it
The following might work:
Get the list of the tables you're interested in. You already do that.
Create a UNION of multiple SELECT statements. Each SELECT statement differs for the table being selected from and you add a column set to the name of the table (so you can identify it later):
(SELECT *, TABLENAME = 'first_name_of_table' FROM first_name_of_table ...)
UNION
(SELECT *, TABLENAME = 'second_name_of_table' FROM second_name_of_table ...)
UNION
...
ORDER BY RAND() LIMIT 10;
Because it is a UNION you can randomize the whole order then. See How can i optimize MySQL's ORDER BY RAND() function? because it is not that trivial to do well, the example above is only to have an ORDER BY and LIMIT clause placed there. With many entries in your tables, it will kill your server.
$aa=array()
while($c = mysql_fetch_array($r))
{
/*display the results randomly with an identifier where the come from*/
$aa[]=$c;
}
echo $aa; // print "Array"

Does mysql_fetch_array reset the query var?

For example I have a mysql query that gets some data. Then runs another query based some of the data that it got.
If i just return the first query, in my case $qOne. Everything works great.
BUT, after using my while loop while ($row = mysql_fetch_array($qOne)) It then returns as an empty array. (but the second query I return DOES work)
I tried to see if I could "save" the first query in another var im not messing with like this $savedResult = $qOne, then i'd just return the $savedResult but that did not work.
Does anyone know how I can get my function below to return both of the results? Thanks!
function getFoods($sort, $start, $limit) {
$qOne = mysql_query("SELECT a.id, a.name, a.type, AVG(b.r) AS fra, COUNT(b.id) as tvotes FROM `foods` a LEFT JOIN `foods_ratings` b ON a.id = b.id GROUP BY a.id ORDER BY fra DESC, tvotes DESC LIMIT $start, $limit;");
$i = 0;
$qry = "";
while ($row = mysql_fetch_array($qOne)) {
$fid = $row['id'];
if ($i > 0)
$qry .= " UNION ";
$i++;
$qry .= "SELECT fid, ing, amount FROM foods_ing WHERE fid='$fid'";
}
$qTwo = mysql_query($qry);
return array($qOne, $qTwo);
}
When you have returned the two query result resources, remember that you will need to fetch from them when you actually want to use them. (we don't see the code where you implement that).
To make use of $qOne after you already have looped through it, you must rewind it back to the first position. That is done with mysql_data_seek()
mysql_data_seek($qOne, 0);

Categories