Getting data from multiple tables into single row while - php

I'm trying to retrieve data from 2 tables and combine multiple rows into a single while loop
posts
post_id content
------ -------
1 content1
2 content2
3 content3
4 content4
comments
id post_id content
------ ------ ------
1 1 Wharton university
1 2 Yale University
sql code I write
mysqli_query( $connect, "SELECT * FROM `posts`
INNER JOIN comments ON posts.post_id = comments.post_id ORDER BY 1 DESC");
The problem I'm only getting post id 1 and 2. while there are over 30 posts
I want to get all posts and comments for each post in a single while loop.
How can I do it ?

Change your join to a LEFT join instead of an INNER join.
The difference being that a LEFT join will use null when there's no comments, where as INNER will only give you the rows that have comments.

Your INNER join is taking the union of both tables on the post_id field. You need a LEFT join instead of an INNER join. The LEFT join will give you all the results from the first table.

Related

How to check if similar values exist across multiple tables

I've read and reviewed numerous posts on here (and elsewhere) about how to do this, but my results seem to be working backwards from what makes sense.
I have 4 tables that have different columns/data, but the columns I need to select from are the same and have the same structure.
Table 1: | id | item_id | user | other table 1 specific columns...<br>
Table 2: | id | item_id | user | other table 2 specific columns...<br>
Table 3: | id | item_id | user | other table 3 specific columns...<br>
Table 4: | id | item_id | user | other table 4 specific columns...<br>
I am trying to check to see if a specific user/item_id combination exists across all 4 tables in 1 query instead of 4.
If I'm reading all the posts correctly, I should do a UNION ALL between the SELECT statements, however, I'm actually getting the reverse of what is making sense.
To keep things simple, I am just testing this with Table 1 and Table 2.
Table 1 does NOT have the combination I'm looking for.
Table 2 does have the combination I'm looking for.
SELECT item_id AS table1ID
FROM table1
WHERE item_id=35 AND user='usernamehere'
UNION ALL
SELECT item_id AS table2ID
FROM table2
WHERE item_id=35 AND user='usernamehere'
So, what I was expecting to see was a null result from Table 1 and a result with the item_id from Table 2, but what's happening is I'm getting no result at all from Table 2 and a "hit" from Table 1.
Seems backwards and confusing since Table 1 doesn't actually have a record with item_id=35 and user='usernamehere'.
Any advice or insights are greatly appreciated.
Your query is just listing item_id's in the specific table. It does not specify where they come from. For two table, you can solve the problem using a join.
I think for more tables, you will want something like this:
select item_id, group_concat(which order by which) as tables
from ((select item_id, user, 'table1' as which from table1) union all
(select item_id, user, 'table2' from table1) union all
(select item_id, user, 'table3' from table1) union all
(select item_id, user, 'table4' from table1)
) t
where user = 'usernamehere'
group by item_id;
For each item_id, this will list the tables it is in. If you want items in all four tables. then add a having clause:
having count(distinct which) = 4;
Similarly, if you want examples where one or more are missing:
having count(distinct which) < 4;
Assuming $var has your search field:
select
inp.ID,
count(t1.itemID) as TableOne,
count(t2.itemID) as TableTwo,
count(t2.itemID) as TableThree,
count(t3.itemID) as TableFour
from
(
select
".$var." as ID
from
dual
) inp
left outer join
table1 t1
on inp.ID=t1.item_id
left outer join
table2 t2
on inp.ID=t1.item_id
left outer join
table3 t3
on inp.ID=t1.item_id
left outer join
table4 t4
on inp.ID=t1.item_id
group by
inp.ID
This will give you a count of whether the item is in your tables via a select you create and outer joins to your other tables which you can count nicely.
UNION will merge results (rows), I don't think it's what you need.
Consider using JOIN statement:
SELECT exTable.ID
FROM exTable as t1
JOIN t2 as t2 ON t1.col = t2.col // we have value of col in t2 same as in t1
JOIN t3 as t3 ON t1.col = t3.col
JOIN t4 as t4 ON t1.col = t4.col
WHERE t1.ID = 35 AND t1.user = 'usernamehere'
In some cases you may use LEFT OR RIGHT joins, you can read about them on W3C.

Getting records from more than 2 tables using join

Here is my table structure:
Table 1
id | question | posted_id
Table 2
id | username | email
Table 3
id | reader_id | quote_id
I want to fetch those question which are not read by particular user.I also want email from table2 in result set. So I created Below query that join my two table1 and table2.
My query:
SELECT table1.id,table1.question,table1.posted_id,table2.email
FROM table1,table2
WHERE table1.post_id = table.id;
How to fix a left join on table 3 for filter the records Because I need questions which are not read by particular user.
I am not sure which user field you are trying to match against, i have taken email, Also this will only give matching records, Try
SELECT T1.*,T2.email
FROM Table1 AS T1
INNER JOIN Table2 AS T2 ON T2.quote_id = T1.id
INNER JOIN Table3 AS T3 ON T3.reader_id = T2.id
WHERE T2.email='some_mail_id'

SQL Join query using three tables and some null values

I have three tables in a mySQL database that I am querying with PHP:
players
player_id | player_name
-----------------------
1 Tom
2 Dick
3 Harry
games
game_id | game_name
-------------------
1 Tennis
2 Cricket
3 Rugby
gamePlayerRel
game_id | player_id
-------------------
1 2
1 3
2 3
3 2
3 3
I want a query that will return the players id and name as well as the games that they play. If they play no games - as in the case of Tom (1) - then I want the id and name and a null or 0 value.
Desired Result
player_id | player_name | game_id | game_name
---------------------------------------------
1 Tom null null
2 Dick 1 Tennis
2 Dick 3 Rugby
3 Harry 1 Tennis
3 Harry 2 Cricket
3 Harry 3 Rugby
The closest I can get is with the following query:
SELECT players.player_id, players.player_name, gamePlayerRel.game_id, games.game_name
FROM players
INNER JOIN gamePlayerRel
INNER JOIN games
ON players.player_id = gamePlayerRel.player_id
AND gamePlayerRel.game_id=games.game_id
This gets close except that it does not return data for players with games assigned to them. In the above examples the result is as I want except that Tom (1) with his null values is left out.
I'm a super noob at this so if I'm coming at it from the wrong angle please say so and if you can suggest a query that will do what I'm after you would make my day.
Thanks in advance for any help and advice.
To return the result set as you've shown you need to actually do two outer joins
SELECT players.player_id, players.player_name, gamePlayerRel.game_id, games.game_name
FROM players
LEFT OUTER JOIN gamePlayerRel ON players.player_id = gamePlayerRel.player_id
LEFT OUTER JOIN games ON gamePlayerRel.game_id=games.game_id
In your case this should work just fine, however, what I really think you're trying to do is an inner join between games and gamePlayerRel and then a Left Outer Join between that virtual table and the players table. You can accomplish that via something like this:
SELECT players.player_id, players.player_name, playerGames.game_id, playerGames.game_name
FROM players
LEFT OUTER JOIN (Select gameplayerRel.player_id, games.game_id, games.game_name from games inner join gamePlayerRel on games.game_id = gamePlayerRel.game_id) playerGames
on players.player_id = playerGames.player_id
In your case you'd never need this alternative syntax, but there are some times when things can get messed up because the two left outer joins way is not exactly logically equivalent.
Here is a SQL Fiddle showing the results of the queries
I know you're using mysql, but this article does a good job of explaining the nuances of the joins, but it is written for MSSQL, although it should apply to you just the same. http://weblogs.sqlteam.com/jeffs/archive/2007/10/11/mixing-inner-outer-joins-sql.aspx
This should do the trick
SELECT players.player_id, players.player_name, gamePlayerRel.game_id, games.game_name
FROM players
INNER JOIN gamePlayerRel ON players.player_id = gamePlayerRel.player_id
LEFT OUTER JOIN games ON gamePlayerRel.game_id=games.game_id
You need to join each table individually and also need to use a LEFT OUTER JOIN for your games table. This will pull in at least one record for every match in the players/gamePlayerRel tables. If there isn't a match you'll be returned a NULL value.
After being nudged in the right direction by the helpful folk of SO I have got a query that does what I am after though I am still not 100% sure why it works.
SELECT players.player_id, players.player_name, gamePlayerRel.game_id, games.game_name
FROM players
INNER JOIN gamePlayerRel ON players.player_id = gamePlayerRel.player_id
LEFT OUTER JOIN games ON gamePlayerRel.game_id=games.game_id
Thanks to those who commented. Once again this site proves one of the most useful I have ever found :)

Count users from table 2 in request to table 1

I have table with positions
tbl_positions
id position
1 Driver
2 Lobby
3 Support
4 Constructor
and in other table i have users
tbl_workers
id name position
1 John 2
2 Mike 3
3 Kate 2
4 Andy 1
i do request of positions
SELECT position FROM tbl_positions
but i also need to show how many workers are assigned to each position i tried to do separate request
SELECT id FROM tbl_workers WHERE position = 2
but cannot display all together in table cannot bind number of users to position.
How can i make join this queries into one, so it also show positions without workers assigned?
join and group by
SELECT p.id, p.position, count(*) FROM tbl_positions as p
inner join tbl_workers as w on w.position=p.id
group by p.id, p.position

Problem with left outer join

I have 2 tables.
Table 1 : t_atc_list
id | a_name | s_title | r_name
------------------------------
80 | ss | 128 | 5
Where s_title & r_name is foreign key.
Table 2 : t_s_list
s_id | title
-------------
128 | Song Title
I want have used left join query on this..to select all values of 't_atc_list' if it mightbe in 't_s_list'..
$query=mysql_query("SELECT t.s_title, s.title from t_atc_list t LEFT OUTER JOIN t_s_list s ON t.s_title=s.s_id");
$row=mysql_fetch_array($query);
While if I use right join its working..
$query=mysql_query("SELECT t.s_title, s.title from t_s_list s RIGHT OUTER JOIN t_atc_list t ON t.s_title=s.s_id");
$row=mysql_fetch_array($query);
Whats the reason left join is not working but right join is going well? And I think both the queries are identical than whats the problem?
This is a strictly data related issue you have there, your SQL syntax is correct, but your data must not line up.
For a visualization of SQL, look here: http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
Also if you do a right join, that means you are simply getting data from the 2nd table, and nulls in the first. I am just guessing here as I see no real data examples.

Categories