SQL Query Running super slow - php

The code I'm running below runs really quite fine, until I try and fetch the Quantity in the last loop. I think it could probably be optimized with JOINs etc but I'm not overly familiar with the best approach for this when grabbing DISTINCT elements?
$sql_dept = "SELECT DISTINCT `department_guid` FROM `bom_material_copy` WHERE `complex_guid`='9EB75BE9-26E2-AEBB-1B52-37DBC2FB89EA' ORDER BY `id` DESC LIMIT 0,5";
foreach($pdo->query($sql_dept) AS $dept)
{
$sql_mat = "SELECT DISTINCT `material_bct_number` FROM `bom_material_copy` WHERE
`complex_guid`='9EB75BE9-26E2-AEBB-1B52-37DBC2FB89EA' AND
`department_guid`='".$dept['department_guid']."'
ORDER BY `id` DESC LIMIT 0,5";
foreach($pdo->query($sql_mat) AS $mat)
{
echo "<tr>";
echo "<td>".$mat['material_bct_number']."</td>";
// Grab Units Again
$u = 0;
$sql_unit = "SELECT DISTINCT `unit_number` FROM `bom_projects_units` WHERE `complex_guid`='9EB75BE9-26E2-AEBB-1B52-37DBC2FB89EA'";
foreach($pdo->query($sql_unit) AS $unit)
{
$sql_quan = "SELECT `quantity` FROM `bom_material_copy`
WHERE
`material_bct_number`='".$mat['material_bct_number']."' AND
`unit_number`='".$unit['unit_number']."' AND
`department_guid`='".$dept['department_guid']."'";
foreach($pdo->query($sql_quan) AS $quan)
{
echo "<td>".$quan['quantity']."</td>";
}
}
echo "</tr>";
}
}

Try using EXPLAIN in your queries.
When you do that, you know the relationship between tables that you're using in the query.
Next step, use INDEX in the fields that you're making match, and execute again you're queries.

Related

How can I convert these two queries in a loop into a single JOINed query?

I am currently trying to get data from my table (mostKills by Weapon in a table with over 300 kills). Initially I did a normal query
$q = $mysql->query("SELECT * FROM `kills`") or die($mysql->error);
but when I tried to
$query2 = $mysql->query("SELECT `killerID`, COUNT(`killerID`) AS tot_kills FROM `kills` WHERE `killText` LIKE '%$gun%' GROUP BY `killerID` ORDER BY `tot_kills` DESC;") or die($mysql->error);
$kData = $query2->fetch_assoc();
$query3 = $mysql->query("SELECT `Username` FROM `players` WHERE `ID` = '" . $kData['killerID'] . "'") or die($mysql->error);
$uData = $query3->fetch_assoc();
$array[$gun]['Kills']++;
$array[$gun]['Gun'] = $gun;
$array[$gun]['BestKiller'] = $uData['Username'];
$array[$gun]['killAmount'] = $kData['tot_kills'];
function sortByKills($a, $b) {
return $b['Kills'] - $a['Kills'];
}
usort($array, 'sortByKills');
foreach($array as $i => $value)
{
// table here
}
I had to do it in a while loop, which caused there to be around 600 queries, and that is obviously not acceptable. Do you have any tips on how I can optimize this, or even turn this into a single query?
I heared JOIN is good for this, but I don't know much about it, and was wondering if you guys could help me
Try this...
I added a inner join and added a username to your select clause. The MIN() is just a way to include the username column in the select and will not have an impact on you result as long as you have just 1 username for every Killerid
SELECT `killerID`
, COUNT(`killerID`) AS tot_kills
, MIN(`Username`) AS username
FROM `kills`
INNER JOIN `players`
ON `players`.`id` = `kills`.`killerid`
WHERE `killText` LIKE '%$gun%'
GROUP BY `killerID`
ORDER BY `tot_kills` DESC
SELECT kills.killerID, count(kills.killerID) as killTotal, players.Username
FROM kills, players
WHERE kills.killText
LIKE '%$gun%'
AND players.ID` = kills.killerID
GROUP BY kills.killerID
ORDER BY kills.tot_kills DESC
Here is a good place to learn some more about joins.
http://www.sitepoint.com/understanding-sql-joins-mysql-database/
The best way is to have your own knowledge so you can be able to tune up your select queries.
Also put more indexes to your DB, and try to search and join by index.

How-to SELECT two tables in query

I am trying to get data of 'indication' from two different tables.
The script works fine when selecting FROM number_one only.
Did try this with a , inbetween but that doesn't work.
How should I do this?
query2 = mysql_query("SELECT `indication` FROM `number_one`, `number_two` ORDER BY `indication` DESC");
while($row2 = mysql_fetch_object($query2)){
if($explode2[1] == $row2->indication){
echo "<option value=\"$row2->indication\" selected=\"selected\">$row2->indication</option>";
}
else{
echo "<option value=\"$row2->indication\">$row2->indication</option>";
}
}
Solution
query2 = mysql_query("SELECT `indication` FROM `number_one` UNION ALL SELECT `indication` FROM `number_two` ORDER BY `indication` DESC");
while($row2 = mysql_fetch_object($query2)){
if($explode2[1] == $row2->indication){
echo "<option value=\"$row2->indication\" selected=\"selected\">$row2->indication</option>";
}
else{
echo "<option value=\"$row2->indication\">$row2->indication</option>";
}
}
Assuming you have two tables, number_one and number_two with the indication column, your query would cross-join the two tables, giving you a set of rows which each have two columns (number_one.indication and number_two.indication, in all the possible combinations.
If I understand the question correctly, you want to have them as one column, with all the values from both tables. This can be done using the UNION ALL set operator, as I demonstrate below:
SELECT indication
FROM ( SELECT indication
FROM number_one
UNION ALL
SELECT indication
FROM number_two)
ORDER BY 1 DESC

How do I add a limit to query results in a if statement?

I have a query I am using where I'm displaying the results in 3 different areas. One of the areas I want to not set a limit and two of them I want to limit them to one. I was thinking in the foreach of those specific two areas I could add the limits there. I'm just not sure how to do that, and if that's the best way.
Here is my query:
$comments_query = "SELECT * FROM airwaves_comments aw,users u WHERE u.id=aw.from_id AND aw.FROM_id=aw.to_id AND aw.from_id=".$profile_id." order by aw.created_on desc" ;
Here is are the results being displayed where I don't want a limit.
if ($airwave)
{
foreach ($airwave as $airwave_comment_row)
{
// stuff
}
}
Here are the results being displayed where I want to limit to one:
if ($airwave && $profile_id == $session_id)
{
foreach ($airwave as $airwave_comment_row)
{
echo "<div id='profile_airwave'>";
echo $airwave_comment_row['comment'];
echo "<br />";
echo "<span class='profile_airwave_info'>";
echo $airwave_comment_row['created_on'];
echo "</span>";
echo "</div>";
}
}
Is this possible, for them to share the same query? Or do I have to write a new query?
thanks
You can change your query like this,
$comments_query = "SELECT * FROM airwaves_comments aw,users u WHERE u.id=aw.from_id AND aw.FROM_id=aw.to_id AND aw.from_id=".$profile_id." order by aw.created_on desc" ;
if($profile_id == $session_id){
$comments_query .= " LIMIT 0,1"
}
OR
You can try with the same logic you have
if ($airwave && $profile_id == $session_id)
$airwave_comment_row = $airwave[0];
// takes the first row
}else if($airwave){
foreach ($airwave as $airwave_comment_row)
{
// stuff
}
}
I think you can do with with a UNION query, but you would need to check if that's the best approach - if it works.
I would check, but I don'y have access to a MySQL server at present.
(SELECT * FROM table WHERE category = 1)
UNION
(SELECT * FROM table WHERE category = 2 LIMIT 10)
UNION
(SELECT * FROM table WHERE category = 3)
Anthony.

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"

mysql multiple table query inside php loop

Faily new to php and mysql, this will probably seem very messy.
This is what I came up with:
$query = "show tables like 'whatever%'";
$result = mysql_query($query);
$num_results = mysql_num_rows($result);
for ($i = 0; $i < $num_results; $i++)
{
$row = mysql_fetch_array($result);
$sql=mysql_query("SELECT * FROM ". $row[0] ." WHERE a=(SELECT MAX(a)) AND b=(SELECT MAX(b)) AND c LIKE 'd%' ORDER BY date DESC LIMIT 1");
while($info=mysql_fetch_array($sql)){
echo "...";
}
}
I get the desired value from each table, so x results depending on the amount of tables. What I would like is to have the results of the queried tables but only show the top 10-5 ordered by date/time.
Is this possible with the current script? Is there an easier way (while, number of tables changing constantly)? Is this query method database intensif?
Cheers!
I call constantly changing number of tables having similar structure a design error. also query switch to
$sql=mysql_query("SELECT * FROM $tbl WHERE c LIKE 'd%' ORDER BY a DESC, b DESC, date DESC LIMIT 1");
is a little relief to database.

Categories