How do you reference multiple lookups from the same table? - php

This is my first post, but I've been reading here for ages taking in a lot of great information.
Please bear with me as I try to explain my predicament. I wasn't even sure how to label my question, since I don't really know the terminology for what I'm trying to do. I'm a beginner of PHP/MySQL (this will become painfully obvious when you see my question), but I'm eager to learn.
Anyway, here goes:
I have two tables, named Games and Teams.
mysql> describe games;
+-----------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| homeTeam | int(11) | NO | | NULL | |
| awayTeam | int(11) | NO | | NULL | |
| homeScore | int(11) | NO | | NULL | |
| awayScore | int(11) | NO | | NULL | |
| homeOdds | decimal(10,2) | NO | | NULL | |
| drawOdds | decimal(10,2) | NO | | NULL | |
| awayOdds | decimal(10,2) | NO | | NULL | |
| gameDate | date | NO | | NULL | |
+-----------+---------------+------+-----+---------+----------------+
and
mysql> describe teams;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| team | varchar(255) | NO | | NULL | |
+-------+--------------+------+-----+---------+----------------+
I would like the fields Games.homeTeam and Games.awayTeam to do a lookup for their values in the Teams.id and Teams.team fields. Basically Games.homeTeam should find its equivalent in Teams.id. Simple enough. However, I would like both Games.homeTeam and Games.awayTeam to look in the Teams table within the same SQL statement.
I figured maybe something like this would work:
$result = mysql_query("SELECT * FROM Games g, Teams ht, Teams at where g.homeTeam = ht.id AND g.awayTeam = at.id ORDER BY g.gameDate") or die(mysql_error());
and then to pick the rows up:
while($row = mysql_fetch_array($result)) { echo "Home Team: " . $row['ht.team'];}
That's a no go, as I get a mysql error saying there's no index named ht.team.
I hope it's fairly clear what I'm trying to achieve here. How should I go about this? I assume I have to use aliases of some sort, but I can't wrap my head around as to what the SQL statement should look like to accomplish what I want.

Don't use SELECT * with join queries! Always be explicit about the columns you need in your SELECT list, and supply column aliases:
SELECT
/* Only select the columns you actually need, and
* supply aliases to those with similar names
*/
ht.team AS ht_team,
ht.id AS ht_id,
at.team AS at_team,
at.id AS at_id
g.homeScore,
g.awayScore,
g.homeOdds,
g.drawOdds,
g.awayOdds,
g.gameDate
FROM
Games g,
Teams ht,
Teams at
where g.homeTeam = ht.id AND g.awayTeam = at.id
ORDER BY g.gameDate
In your PHP, access them via their aliases, for example:
echo "Home Team: {$row['ht_team']}";
By the way, although your method of implicit (comma-separated tables and conditions in the WHERE clause) joins will work, using explicit joining is often recommended. It is a newer syntax, and will allow easier expansion into LEFT JOIN or RIGHT JOIN when the need arises:
SELECT
ht.team AS ht_team,
ht.id AS ht_id,
at.team AS at_team,
at.id AS at_id
g.homeScore,
g.awayScore,
g.homeOdds,
g.drawOdds,
g.awayOdds,
g.gameDate
FROM
/* Explicit JOIN syntax */
Games g,
JOIN Teams ht ON g.homeTeam = ht.id
JOIN Teams at ON g.awayTeam = at.id
ORDER BY g.gameDate

I think the problem is
you give an alias to the table only , not to the column
if there is not a column in Games table with the name team
you can call it in your loop with only
$row['team'];
However if both of table have the same name column like team
so you should do this .
select ht.team as htTeam , g.team as gTeam from Teams ht inner join
Games on ht.Id = .....
Then you can reach each team term with
$row['htTeam']
and $row['gTeam'];
and I think get used to decide a prefix for tables and the their columns

Related

PHP/MySQL Compare against a date

I'm running into a little issue concerning a datetime picker and MySQL.
I have a PHP script that should get records before (and including) the selected day. However, the dataset returns empty.
Here's the SQL part of the script:
$sql = 'SELECT `pro_title`,
`pro_part_number`,
`name` AS flag_name,
`old_val`,
`new_val`
FROM `products`
INNER JOIN `flags` ON `id` = `pro_flag_id`
INNER JOIN `flag_history` ON `pro_part_number` = `part`
WHERE `pro_flag_id` IN(:flags)
AND STR_TO_DATE(`ts`, "%y-%m-%d") <= :dateTs;';
I then use PDO to bind the params:
array(
':flags' => implode(',', $flags), # this outputs 1,2,3
':dateTs' => $date # this outputs 2019-04-30
)
I've also tried changing <= to >= to no avail (not that it should work, but thought I'd try).
I've come across a good few SO posts but nothing has actually got me there. Here is the description of the flag_history table (where ts is stored)
MariaDB [mastern]> describe `flag_history`;
+---------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| part | varchar(25) | NO | | NULL | |
| ts | datetime | YES | | CURRENT_TIMESTAMP | |
| old_val | int(4) | YES | | NULL | |
| new_val | int(4) | YES | | NULL | |
+---------+-------------+------+-----+-------------------+----------------+
And some example data:
MariaDB [mastern]> select * from `flag_history` order by `id` desc limit 5;
+-------+----------+---------------------+---------+---------+
| id | part | ts | old_val | new_val |
+-------+----------+---------------------+---------+---------+
| 24026 | PART-001 | 2019-04-30 09:42:22 | 0 | 3 |
| 24025 | PART-002 | 2019-04-30 09:42:22 | 0 | 3 |
| 24024 | PART-003 | 2019-04-30 09:42:22 | 0 | 3 |
| 24023 | PART-004 | 2019-04-30 09:42:22 | 0 | 3 |
| 24022 | PART-005 | 2019-04-30 09:42:22 | 0 | 3 |
+-------+----------+---------------------+---------+---------+
Then, using PART-001 to make sure the flag_id is actually set:
MariaDB [mastern]> select `pro_flag_id` from `products` where `pro_part_number` = "PART-001";
+-------------+
| pro_flag_id |
+-------------+
| 3 |
+-------------+
So I'm not really sure what's going wrong, the logic and everything to me (MySQL newb) looks like it should work but it's giving me empty data. I also tried changing the INNER JOIN's to LEFT JOIN's but again, didn't work.
What am I doing wrong?
I managed to solve it. As I'm really reading the flag_history table, I changed the main SELECT focus to flag_history, revised SQL:
$sql = 'SELECT `old_val`, `new_val`, `ts`, `flags`.`name` AS flag_name, `pro_part_number`, `pro_title`
FROM `flag_history`
INNER JOIN `products` ON `pro_part_number` = `part`
INNER JOIN `flags` ON `pro_flag_id` = `flags`.`id`
WHERE `ts` <= :dateTs;';
I slowly added in the INNER JOIN's and managed to get it working when using flag_history. I think the issue actually may have been down to the id field. Being an ambiguous field (flags and flag_history have the id column). Weirdly, I wasn't getting that error though (maybe as I wasn't selecting). Either way managed to resolve it by being more specific with my select and going from the read-table rather than joining it.
On a further note, removing the flags segment from the JOIN shows the constraint error. So my guess is that it didn't show first time as I was reading from a different table.

This Mysql SQL Select query takes 33 mins to execute

Title says it all. Do you think anyone could help me untangle this? or if someone could point me out to what else could be causing it to take so much time. The query takes about half an hour to run. The guy who wrote this tried doing it in a loop, by removing the table from the last join statement and then querying the field.title for each vote. i was hoping to bring the result to about 5 mins.
some extra info:
The query result is 83,531 rows
The vote table size is 30 MB (261,169 rows)
SELECT `vote`.`id` `vote_id`, `branch`.`name` `branch`, `brand`.`name` `brand`, DATE(vote.created_at) `date`, HOUR(vote.created_at) `time_hour`,
MINUTE(vote.created_at) `time_minute`, `vote`.`is_like`, `voter`.`name`, `voter`.`telephone`, `voter`.`email`, popups_votes.title `popup_title`,
popups_votes.value `popup_value`, GROUP_CONCAT(dis.field SEPARATOR '|') `reasons`
FROM (`vote`)
LEFT JOIN `voter` ON `voter`.`id` = `vote`.`voter_id`
LEFT JOIN `device` ON `device`.`id` = `vote`.`device_id`
LEFT JOIN `branch` ON `branch`.`id` = `device`.`branch_id`
LEFT JOIN `brand` ON `brand`.`id` = `branch`.`brand_id`
LEFT JOIN `popups_votes` ON popups_votes.vote_id = vote.id
LEFT JOIN (SELECT vote_dislike.vote_id `vote_id`, field.title `field` FROM vote_dislike
LEFT JOIN branch_dislike_field ON branch_dislike_field.id = vote_dislike.branch_dislike_id
LEFT JOIN field ON field.id = branch_dislike_field.field_id) dis
ON dis.vote_id = vote.id
WHERE (vote.device_id in
(
Select d.id
From device d
WHERE d.branch_id IN (SELECT id FROM branch WHERE brand_id = 7)
)
)
AND (vote.created_at >= FROM_UNIXTIME('$from_time') AND vote.created_at <= FROM_UNIXTIME('$to_time') )
GROUP BY vote.id
EDIT: this is the explain {query} output:
+------+-------------+----------------------+--------+----------------------+-----------+---------+-------------------------------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------------------+--------+----------------------+-----------+---------+-------------------------------------------+------+----------------------------------------------+
| 1 | PRIMARY | branch | ref | PRIMARY,brand_id | brand_id | 4 | const | 20 | Using index; Using temporary; Using filesort |
| 1 | PRIMARY | d | ref | PRIMARY,branch_id | branch_id | 4 | river_back.branch.id | 1 | Using index |
| 1 | PRIMARY | vote | ref | device_id,created_at | device_id | 4 | river_back.d.id | 1200 | Using where |
| 1 | PRIMARY | voter | eq_ref | PRIMARY | PRIMARY | 4 | river_back.vote.voter_id | 1 | |
| 1 | PRIMARY | device | eq_ref | PRIMARY | PRIMARY | 4 | river_back.d.id | 1 | |
| 1 | PRIMARY | branch | eq_ref | PRIMARY | PRIMARY | 4 | river_back.device.branch_id | 1 | Using where |
| 1 | PRIMARY | brand | eq_ref | PRIMARY | PRIMARY | 4 | river_back.branch.brand_id | 1 | Using where |
| 1 | PRIMARY | popups_votes | ref | vote_id | vote_id | 5 | river_back.vote.id | 602 | |
| 1 | PRIMARY | vote_dislike | ref | vote_id | vote_id | 4 | river_back.vote.id | 1 | |
| 1 | PRIMARY | branch_dislike_field | eq_ref | PRIMARY | PRIMARY | 4 | river_back.vote_dislike.branch_dislike_id | 1 | Using where |
| 1 | PRIMARY | field | eq_ref | PRIMARY | PRIMARY | 4 | river_back.branch_dislike_field.field_id | 1 | Using where |
+------+-------------+----------------------+--------+----------------------+-----------+---------+-------------------------------------------+------+----------------------------------------------+
You should check that all the data you are selecting are indexed and you have foreign keys.
How do MySQL indexes work?
Basically an index on a table works like an index in a book (that's
where the name came from):
Let's say you have a book about databases and you want to find some
information about, say, storage. Without an index (assuming no other
aid, such as a table of contents) you'd have to go through the pages
one by one, until you found the topic (that's a full table scan). On
the other hand, an index has a list of keywords, so you'd consult the
index and see that storage is mentioned on pages 113-120,231 and 354.
Then you could flip to those pages directly, without searching (that's
a search with an index, somewhat faster).
Basics of Foreign Keys in MySQL?
FOREIGN KEYS just ensure your data are consistent.
They do not improve queries in sense of efficiency, they just make
some wrong queries fail.
Do not use LEFT unless you are expecting the "right" table to have missing rows.
In particular, the Optimizer probably cannot start with the 'derived table' since it is hiding to the right of a LEFT.
Do not use IN ( SELECT ... ); if possible change to EXISTS ( SELECT * ...) or JOIN.
Try to avoid the "inflate-deflate" caused by JOIN ... GROUP BY. If possible find the ids of interest without needing a GROUP BY, then JOIN to the other tables.
Putting many of those together, does this get you close to the desired result, at least in the sense of getting the correct vote.id values?
SELECT vote.id
FROM vote AS v
JOIN (
SELECT vote_dislike.vote_id `vote_id`, field.title `field`
FROM vote_dislike AS vd
LEFT JOIN branch_dislike_field AS bd
ON bd.id = vd.branch_dislike_id
LEFT JOIN field
ON field.id = bd.field_id
) AS dis ON dis.vote_id = v.id
JOIN device AS d ON v.device_id = d.id
JOIN branch AS b ON d.branch_id = b.id
WHERE b.brand_id = 7
AND v.created_at >= ...
AND v.created_at <= ...
Then:
SELECT lots of stuff
FROM ( the above query ) AS x
JOIN vote v ON x.id = v.id -- yes, dig back into `vote` for the other stuff
JOIN voter ...
JOIN ...
but with no GROUP BY.

PHP MySQL joining two tables with conditional joins

So, I have a database that I am creating. It stores information about families and each family member. It then uses those records to associate invoices to either a family or family member.
My dilemma is that I need to list all of these invoices to a page under the families record i.e. create a list of invoices associated to either the family itself or an individual family member.
Table Structure
invoices
id | date_entered | invoice_date | invoice_number | invoice_amount | client_type | unique_id | supplier_type | supplier_id | category_id | childcare_hours
---+--------------+--------------+----------------+----------------+-------------+-----------+---------------+-------------+-------------+----------------
1 | 1411098397 | 1411048800 | 123 | 0.01 | 0 | 137 | 0 | 139 | 5 | NULL
families
id | ufi | last_name | address_1 | address_2 | city_id | phone | mobile | email | f_d_worker_1 | f_d_worker_2 | status_id | trans_date | entry_date | exit_date | eligible_date | active_date | lga_loc_id | facs_loc_id | ind_status_id | referral_id | active_status | comm_org_id | notes
---+----------+-----------------+-------------+-----------+---------+-------+--------+-------+--------------+--------------+-----------+------------+------------+-----------+---------------+-------------+------------+-------------+---------------+-------------+---------------+-------------+-------
1 | 1-XEWUDZ | Forsyth - Ennis | Skinner St. | NULL | NULL | NULL | NULL | NULL | 13 | NULL | 1 | NULL | 1341324000 | NULL | 1341842400 | 1342620000 | 7 | 1 | 3 | NULL | 1 | 1 | NULL
clients (family members)
id | upi | last_name | first_name | birthdate | sex | phone | mobile | email | indig_status_id | referral_id | relationship_id | preschool_id | family_id | notes
---+----------+-----------+------------+------------+-----+-------+--------+-------+-----------------+-------------+-----------------+--------------+-----------+------
1 | 1-XFCBBP | Ennis | Jason | 20/09/1996 | 1 | NULL | NULL | NULL | 3 | NULL | NULL | NULL | 1 | NULL
My current SQL looks like:
SELECT `invoices`.`id`, `invoices`.`date_entered`, `invoices`.`invoice_date`, `invoices`.`invoice_number`, `invoices`.`invoice_amount`, `invoices`.`client_type`, `invoices`.`unique_id`, `unique1`.`ufi`, `unique2`.`upi`, `unique1`.`last_name`, `invoices`.`supplier_type`, `invoices`.`supplier_id`, `suppliers`.`name`, `invoices`.`category_id`, `cat1`.`name`, `cat2`.`name`, `invoices`.`childcare_hours`
FROM `invoices`
LEFT OUTER JOIN `suppliers` ON `suppliers`.`id` = `invoices`.`supplier_id`
LEFT OUTER JOIN `categories` cat1 ON `cat1`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `preschool_types` cat2 ON `cat2`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `families` unique1 ON `unique1`.`id` = `invoices`.`unique_id`
LEFT OUTER JOIN `clients` unique2 ON `unique2`.`id` = `invoices`.`unique_id`
WHERE (`invoices`.`unique_id` = ? AND `unique1`.`ufi` = ?) LIMIT 0, 10
But what I need a query that checks the client_type column and if it equals 1 it needs to look in the clients table BUT it needs to look for members of the same family, identified by the id row in the families table
SOLUTION
Ok, so after much, much (much) screwing around and a little research. It appears that #cupid was correct (Although very brief in his answer).
And I will explain the solution better (in hope that this will help someone later).
The UNION option in MySQL (and most likely other SQL) allows you to combine the result sets of two (or more) SELECT queries, into one result set. This is extremely helpful if you have similar data, in separate tables that you may want to select easily and process as one request. Also helpful (in my case) for pagination, by allowing you to utilise SQL's LIMIT option.
One thing to take into consideration is that, the UNION syntax uses the columns from the first SELECT statement as the column names for all following queries, also you need to make sure that you have the same amount of columns selected in all queries for this to work.
(
SELECT
`invoices`.`id`,
`invoices`.`date_entered`,
`invoices`.`invoice_date`,
`invoices`.`invoice_number`,
`invoices`.`invoice_amount`,
`invoices`.`client_type`,
`invoices`.`unique_id`,
`clients`.`upi`,
`clients`.`last_name`,
`clients`.`family_id`,
`invoices`.`supplier_type`,
`invoices`.`supplier_id`,
`suppliers`.`name`,
`invoices`.`category_id`,
`cat1`.`name`,
`cat2`.`name`,
`invoices`.`childcare_hours`
FROM
(
`invoices`
LEFT OUTER JOIN `suppliers` ON `suppliers`.`id` = `invoices`.`supplier_id`
LEFT OUTER JOIN `categories` cat1 ON `cat1`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `preschool_types` cat2 ON `cat2`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `clients` ON `clients`.`id` = `invoices`.`unique_id`)
WHERE
`clients`.`family_id` = 47 AND `invoices`.`client_type` = 1
)
UNION
(
SELECT
`invoices`.`id`,
`invoices`.`date_entered`,
`invoices`.`invoice_date`,
`invoices`.`invoice_number`,
`invoices`.`invoice_amount`,
`invoices`.`client_type`,
`invoices`.`unique_id`,
`families`.`ufi`,
`families`.`last_name`,
`families`.`id`,
`invoices`.`supplier_type`,
`invoices`.`supplier_id`,
`suppliers`.`name`,
`invoices`.`category_id`,
`cat1`.`name`,
`cat2`.`name`,
`invoices`.`childcare_hours`
FROM `invoices`
LEFT OUTER JOIN `suppliers` ON `suppliers`.`id` = `invoices`.`supplier_id`
LEFT OUTER JOIN `categories` cat1 ON `cat1`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `preschool_types` cat2 ON `cat2`.`id` = `invoices`.`category_id`
LEFT OUTER JOIN `families` ON `families`.`id` = `invoices`.`unique_id`
WHERE
`invoices`.`unique_id` = 47 AND `invoices`.`client_type` = 0
)
Have you thought about using UNION?

MySQL INNER vs LEFT JOIN different order

Why do this two queries return different result set when they have the same ORDER BY.
Only difference in query is that first time I user INNER JOIN an it takes about 5 seconds.
Second time I used LEFT JOIN and it took 0.05 seconds. In both cases they return exactly 43.000 rows, but tck.id order is different and I can't figure out why or in which way?
SELECT tck.*, acc.ac_name
FROM support_tickets tck
INNER JOIN support_ticket_accounts acc USING (id_support_ticket_account)
WHERE tck.id_company = 2 AND tck.st_status = 1 ORDER BY tck.st_priority DESC
Edit:
SELECT tck.*, acc.ac_name
FROM support_tickets tck
LEFT JOIN support_ticket_accounts acc ON tck.id_support_ticket_account = acc.id_support_ticket_account
WHERE tck.id_company = 2 AND tck.st_status = 1
ORDER BY tck.st_priority DESC;
+----+-------------+-------+--------+---------------+------------+---------+-------------------------------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+------------+---------+-------------------------------+-------+-----------------------------+
| 1 | SIMPLE | tck | ref | id_company | id_company | 5 | const | 37586 | Using where; Using filesort |
| 1 | SIMPLE | acc | eq_ref | PRIMARY | PRIMARY | 4 | tck.id_support_ticket_account | 1 | |
+----+-------------+-------+--------+---------------+------------+---------+-------------------------------+-------+-----------------------------+
SELECT tck.*, acc.ac_name
FROM support_tickets tck
INNER JOIN support_ticket_accounts acc ON tck.id_support_ticket_account = acc.id_support_ticket_account
WHERE tck.id_company = 2 AND tck.st_status = 1
ORDER BY tck.st_priority DESC;
+----+-------------+-------+------+-------------------------------------+----------------------------+---------+-------------------------------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+--------------------------------------+---------------------------+---------+-------------------------------+------+---------------------------------+
| 1 | SIMPLE | acc | ALL | PRIMARY | NULL | NULL | NULL | 5 | Using temporary; Using filesort |
| 1 | SIMPLE | tck | ref | id_company,id_support_ticket_account | id_support_ticket_account | 5 | acc.id_support_ticket_account | 2085 | Using where |
+----+-------------+-------+------+--------------------------------------+---------------------------+---------+-------------------------------+------+---------------------------------+
I think using temporary is responsible for the delay (but I don't see why it's necessary for one query and not the other one). I think creating multi-column index should help:
CREATE INDEX filter
ON support_tickets(id_company, st_status, st_priority)
USING BTREE;
If you just ORDER BY tck.st_priority DESC multiple different recordsets are posible and can be returned, for each of both cases (left or inner). That is because you must have a lot of records that has the same st_priority so any of them can came in no particular order
Add more fields to the order by clause to give any record unique possible position and you will have same order on both querys.

load posts from each friend

I'm currently working on a "news feed" type of script and I am trying to load the posts created by the user's friends. My current code partially works; it only loads from one friend and finishes. What am I doing wrong?
<?php
$infofriends = mysql_fetch_array(mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'"));
$infofrnd = mysql_fetch_array(mysql_query("SELECT * FROM btaccs WHERE `auto`='".$infofriends['friend_id']."'"));
$posts = mysql_query("SELECT * FROM btpost WHERE `user`='".$infofrnd['user']."' ORDER BY `auto` DESC") or die('Error: '.mysql_error());
while($row = mysql_fetch_array( $posts )) {
$infobeer = mysql_fetch_array(mysql_query("SELECT * FROM btbeer WHERE `beer`='".$row['beer']."'"));
$infouser = mysql_fetch_array(mysql_query("SELECT * FROM btaccs WHERE `user`='".$row['user']."'"));
....
(Currently sloppy, I'll be editing that afterwards).
MySQL structures:
btfriend
mysql> DESCRIBE btfriend;
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| auto | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | | NULL | |
| friend_id | int(11) | YES | | NULL | |
+-----------+---------+------+-----+---------+----------------+
btaccs
mysql> DESCRIBE btaccs;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| auto | int(11) | NO | PRI | NULL | auto_increment |
| user | varchar(150) | YES | | NULL | |
| display | varchar(150) | YES | | NULL | |
| pass | varchar(250) | YES | | NULL | |
| email | varchar(150) | YES | | NULL | |
| firstname | varchar(150) | YES | | NULL | |
| lastname | varchar(150) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
btpost
mysql> DESCRIBE btpost;
+---------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------------+------+-----+---------+----------------+
| auto | int(11) | NO | PRI | NULL | auto_increment |
| user | varchar(500) | YES | | NULL | |
| beer | varchar(911) | YES | | NULL | |
| img | varchar(30) | YES | | NULL | |
| rate | varchar(10) | YES | | NULL | |
| loc | varchar(1000) | YES | | NULL | |
| comment | varchar(1500) | YES | | NULL | |
| fb | varchar(10) | YES | | NULL | |
| type | int(2) | YES | | NULL | |
+---------+---------------+------+-----+---------+----------------+
It'd be great if someone could help!
First of all, you're using mysql_* functions; those have been deprecated, and will stop working at some point in the future. Look at switching to mysqli_ or PDO instead - they both make it easier to write safer code.
Secondly, you're calling your code in such a way that you're expecting it to work:
$infofriends = mysql_fetch_array(mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'"));
If the query fails, you'll be passing a boolean false to mysql_fetch_array; it's a lot easier to make each statement one at a time, and handle errors as they come up:
$friendset = mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'") or die (mysql_error());
$infofriends = mysql_fetch_array($friendset) or die (mysql_error());
That will generate an error on the appropriate line if something goes wrong - it's a little more code, but it's much easier to debug and maintain.
Finally, your actual question; you're only getting one friend, because you're only calling mysql_fetch_array() once on the friend query; that will return to the top row. A quick solution would be to loop through the results separately to generate a list, and then pass that into the second query:
$friendset = mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'") or die (mysql_error());
$friendArray = array();
while ($infofriends = mysql_fetch_array($friendset)) {
$friendArray[] = $infofriends['friend_id'];
}
$friendArray[] = $infousr['auto'];
// At this point, you have an array of friend IDs.
$posts = mysql_query("SELECT * FROM btpost INNER JOIN btaccs ON btpost.user=btaccs.user WHERE btaccs.auto IN (" . implode(',', $friendArray) . ") ORDER BY btpost.auto DESC") or die('Error: '.mysql_error());
Note that it's using an IN to retrieve all the IDs at once; you might want to add an extra parameter to the ORDER BY to arrange the posts by friend.
Note that I've not tested this, so there may be issues with the syntax, but I hope it's enough for you to get the general idea.
--
We solved this in the chat and have added $friendArray[] = $infousr['auto']; which would also include the posts from the current user. The current user's ID, along with the friend IDs, would then go into the implode function in the query. We also linked the btpost and btaccs tables because btaccs held the user's ID, while btpost held the username. Full chat transcript -alexpja
Try this with using single query with join
SELECT p.*
FROM btpost p
INNER JOIN btfriend f ON (p.`user` = f.friend_id)
WHERE f.user_id =$infousr['auto']
Then loop through all the results from query,this will give you all the posts where btpost's user is equal to the friend's id btfriend and these are the friends of your given user id $infousr['auto'] I assume $infousr['auto'] will have the user id
I think you're missing a loop. Let's break down your code:
<?php
// Here, you run a query that presumably returns multiple rows, but you're only looking at the first row:
$infofriends = mysql_fetch_array(mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'"));
// That gave you a single array of the first friend that MySQL found
// Now, you take the `friend_id` field from that single result, and you run it against the `btaccs` table to get some more information:
$infofrnd = mysql_fetch_array(mysql_query("SELECT * FROM btaccs WHERE `auto`='".$infofriends['friend_id']."'"));
// Once again, you have a single row at this point. (Although here, I'm assuming that's ok, since a user's ID probably appears only once in this table
// Now, you take the single user that you've looked up, and you find posts associated with that user:
$posts = mysql_query("SELECT * FROM btpost WHERE `user`='".$infofrnd['user']."' ORDER BY `auto` DESC") or die('Error: '.mysql_error());
I think you can see that it's the first statement that limits it to a single user. Try creating an array before running that statement, and then looping through your result set, adding to that array.
A few other things I'd seriously consider:
1) Take advantage of PHP's double-quote string substitution...
mysql_query("SELECT * FROM btfriend WHERE `user_id`='{$infousr['auto']}'"
is a little easier to read than
mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'"
2) Read up on JOINs in MySQL. Everything you've done here can actually be collapsed into a single query in MySQL. It'd be a little too much to go into detail here, but you can start with the MySQL docs: http://dev.mysql.com/doc/refman/5.0/en/join.html

Categories