I am joining two tables: customers and queries.
I am getting the full_name from the customers table and the description from the queries table.
I am wondering if it is possible to have the results of an SQL join split into arrays that correspond with the table the data came from? For example:
$STH = $DBH->prepare("SELECT queries.description, customers.full_name FROM queries INNER JOIN customers ON queries.customer_id = customers.id");
$STH->execute();
$queries = $STH->fetchAll();
At the moment, I can access my data like this: $queries[0]['description'] and $queries[0]['full_name']
However, my question is whether there is an easy way to get the data like so: $job[0]['query']['description'] and $job[0]['customer']['full_name'].
Just as teresko mentioned, I can't understand why you'd need that.
I can only imagine you want to see on the PHP code what are the table that contained the information.
Maybe you could do something like SELECT queries.description as queries_description, then your php code would look like $queries['queries_description']. Would it be enough?
You can loop through the results in PHP and convert it to the data structure you want, but you cannot (as far as I know) automatically group the data into arrays based on the source table. A (somewhat messy) alternative, using SQL is to use a multi-query and create a temp table from your original results, then select the results on a per-table basis, like so:
CREATE TEMPORARY TABLE q AS
(SELECT queries.description, customers.full_name FROM queries
INNER JOIN customers
ON queries.customer_id = customers.id
);
SELECT q.description FROM q;
SELECT q.full_name FROM q;
So, in those SELECT statements, you'll have to list all the columns that you want for each result. Then in PHP, you'll have to iterate over each resultset and put the data into arrays (or objects/whatever) as needed. Errr. A fetchAll will still not get you what you want, but a fetchAll on the first non-empty resultset will get you all the rows from queries and the 2nd will get you all the rows from customers
Related
I am making a SQL teaching program. The students will become their Database and Questions. I want to make it possible for them to write any query they want to and give them the result of it.
So it is possible that they write a query like:
SELECT Person.*, Student.ID
FROM Person JOIN Student JOIN Address
WHERE Address.housenr > 20
This makes it hard to use the
SELECT table_name, column_name
FROM INFORMATION_SCHEMA.COLUMNS;
to get the column names. It would be very nice to get those names right from the results of the query. Is it possible to do that in PHP?
You can use the fetch_fields() method to get any information about the columns in your result set. When your query returns at least one row you can use the normal fetch_assoc() method and read the keys from the returned array via array_keys().
I am using MySql and have a situation which is a lot like a correlated subquery except that the data in the inner query is not in the database - but in a PHP session.
If all the data were in the database, the query would look something like this:
SELECT * FROM tableA WHERE (tableA.valueA && (
SELECT valueB FROM tableB WHERE tableB.id = tableA.id));
My problem is that I have no tableB. Instead I have a PHP array. How can I inject the array into the query? Should I attempt to create a temporary table somewhere? Or perhaps I should be trying to declare the array as a variable?
The information in the PHP array is specific to each user and changes rapidly. Also, there will be lots of queries so performance is a consideration.
See comments from Wrikken above - I have made this a temporary table and it seems to be a fine solution.
I currently have a page that displays player information from one table named "tblplayers". The query I am currently using is:
$result = mysql_query("SELECT * FROM tblPlayers WHERE lng_RecordID_PK = '".$playerid."' ");
I have a second table named "tblMatches" containing match results for the players. I want the recordset to include the rows from "tblMatches" WHERE "P1_ID" OR "P2_ID" is equal to the "lng_RecordID_PK" field from "tblPlayers".
How can I revise my $result query so that it returns:
one row from tblPlayers
multiple rows from tblMatches
???
Thanks for helping me out.
That's called a 'join':
SELECT tblPlayers.*, tblMatches.*
FROM tblPlayers
LEFT JOIN tblMatches ON Ing_RecordID_PK IN (P1_ID, P2_ID)
You are asking about joining two tables where the second table potentially has multiple records for each one in the first table. This is a one-to-many or 1:N join, and most often done using a LEFT JOIN meaning you want everything in the "left" table, and all the records that match from the "right" table, and that you may have some records on the "left" side with no matches.
Your query would look like this:
SELECT *
FROM tblPlayers
LEFT JOIN tblMatches
ON (tblPlayers.lng_RecordID_PK = tblMatches.P1_ID
OR tblPlayers.lng_RecordID_PK = tblMatches.P2_ID)
WHERE tblPlayers.lng_RecordID_PK = #PlayerID;
Bits of advice:
Avoid selecting all columns (*) and instead select just those that you need for the query.
Consider using parameterized queries to avoid SQL injection attacks. If your variable were to be submitted or altered maliciously, it could result in compromised data or security. (See PHP Data Objects for example.)
There is no way to get rows from two different tables in the way you are describing. You could not get a row from one table, and two rows from another one. What you could is do two separate queries, or use a JOIN statement to join the two tables together, and then receive results from the resulting joined table. If you provide more information about your table structure I am sure more help can be given.
Is it ok to a mysql query inside a while loop using the ID of each row passed to fetch results from another table? OR is there a better way to do it?
$q = $__FROG_CONN__->query("SELECT cms_page.id, cms_page.title, cms_page.slug, cms_page_part.* FROM cms_page LEFT JOIN cms_page_part ON cms_page_part.page_id=cms_page.id WHERE cms_page.parent_id='8'");
$r = $q->fetchAll(PDO::FETCH_ASSOC);
echo '<ul id="project-list">';
foreach ($r as $row) {
echo '<li>';
echo '<img src="<img src="phpThumb/phpThumb.php?src=public/images/'.$row[0].'/th.jpg&w=162" alt="" />';
echo '<div class="p-text">';
echo '<h4>'.$row["location"].'<span>'.$row["project_date"].'</span></h4>';
echo '<p>'.$row["body"].'</p>';
echo '</div>';
echo '</li>';
}
echo '</ul>';
I am trying to pull the project_date, body and location fields from another table where the sql query matches. The title and slug are held in another table. There should only be a maximum of eight or so results but im getting alot more.
The suggestions using IN are fine, but if you are getting the ids from another query, it might be better to combine these two queries into one query using a join.
Instead of:
SELECT id FROM users WHERE age <30
SELECT id, x FROM userinfo WHERE userid IN ($id1, $id2, ..., $idn)
do:
SELECT users.id, userinfo.x
FROM users
LEFT JOIN userinfo ON userinfo.userid = users.id
WHERE age < 30
To reduce the overhead of preforming a query, you may want to look at getting all the data in a single query. In which case you may want to take a look at IN(), e.g.
SELECT * WHERE x IN (1, 2);
There is also BETWEEN()
SELECT * WHERE x BETWEEN 1 AND 2;
See the mysql docs for more information
I would try to build the query in a way where I only need to pass it once. Something like WHERE ID=1 OR ID=2 OR ... Passing multiple queries and returning multiple recordsets is expensive in terms of processing and network traffic.
This will be very inefficient, what you want is to join the tables on the ID
SELECT * FROM table1 LEFT JOIN table2 ON (table1.ID = table2.ID) WHERE condition
Mysql join documentation
This will return one set of rows with all the information you need, returned from both tables.
In a small application / small result set, this might be okay, but it results in a lot of (small) calls to the database.
If you can find an alternative way (perhaps see Yacoby's suggestion?) in which you can do one call to the database, this is probably better.
EDIT
If you are only interested in the IDs from one table, in order to get the correct results out of another table, perhaps a JOIN is what you are looking for?
SELECT t1.fieldA, t1.fieldB
FROM table1 t1
JOIN table2 t2 ON t1.ID = t2.ID
WHERE t2.someField = 'someValue'
Is it ok to a mysql query inside a while loop using the ID of each row passed to fetch results from another table? OR is there a better way to do it?
You should reformulate your query in SQL. Say, put the ids into a memory table and use it in a JOIN:
SELECT *
FROM idtable
JOIN mytable
ON mytable.id = idtable.id
This way, MySQL will make the loops for you but will make them in (usually) more efficient way.
SQL is a language designed to work with sets.
So if you have a set of ids and a table (which is a set of tuples), your first thought should be "how do I apply the set-based operations to these sets using SQL"?
Of course it is possible to run a bunch of simple queries in a loop but this way you just do extra work which SQL engine developers most probably have already done for you (and usually have done it in more efficient way).
You may want to read this article in my blog:
Double-thinking in SQL
If you had data in table 1 that you need to use to return data in table 2 for each row returned in table 1. What is more efficient to use a set of querys in PHP one inbedded in the while loop of the other or an SQL function within a query?
for example:
$qry = mysql_query(SELECT date FROM table1)
while($res = mysql_fetch_array($qry))
{
$qry = mysql_query("SELECT name FROM table2 WHERE date=$res['date']")
}
or to do this as a function that returns the Id from table1 within the query.
A (LEFT / RIGHT) JOIN?
Unless I've misunderstood the question...
I think you're looking for JOIN sql syntax. If you have 2 tables: messages and author and you want to return messages with authors. Then you can write following SQL statement:
SELECT m.body, a.name FROM message m
LEFT JOIN author a ON (a.id=m.author_id)
This will return message body with corresponding author name
Table author:
id - primary key
name - name of the author
Table message:
body - text of the message
author_id - id of the author
UPD1:
This will be faster then looping each message and select an author. Because JOIN allows you to return all data in single query (not N x queries when using for loop).
UPD2:
With your tables the query will look like:
SELECT t1.date, t2.name FROM table1 t1 LEFT JOIN table2 t2 ON (t2.date=t1.date)
It depends on if the data is easier to find during the while loop or in the query itself.
So if the DB has to base the sub-query on the result of each row in the main query, and there are 1000 total rows and 100 results in the main query, it has to check all of the rows 100 times, so that's 100,000 sub-queries it runs.
So think it terms of the number of results of the main query. If your while loop has to query the DB 100 times while the DB can do it much faster and efficiently in one query, that's better. But if you want a subset of answers that you can say 'query only based on the last set of results' the while loop is better.
What is more efficient to use
a set of querys in PHP one inbedded in the while loop of the other
or
an SQL function within a query
Seems you answered your question yourself, didn't you?
Every query you send to the dbms has to be sent over the network, parsed, analyzed then executed. You may want to minimize the number of queries sent to the db.
There may be exceptions, for example if the processing of the data requires operations which the dbms is not capable of.