I have a SELECT query from one table that works great as follows:
$sql = "SELECT count(max720) AS anzahlpositive1 from table where (((max720 - lastsignal)/lastsignal)*100) >= 1 AND (((max720 - lastsignal)/lastsignal)*100) < 2 AND max720 != ''";
$result = $conn->query($sql);
But I had 20-30 of them with other values.
For every SELECT query a new connection established.. I think thats a lot of perfomance.
Thats the 2nd:
$sql = "SELECT count(max720) AS anzahlpositive2 from table where (((max720 - lastsignal)/lastsignal)*100) >= 2 AND (((max720 - lastsignal)/lastsignal)*100) < 3 AND max720 != ''";
$result = $conn->query($sql);
Is is possible to do this in ONE select? (better performance)
I have tried with UNION (but i think its for 2 or more tables)
Is that a solution?
$sql = "SELECT 1";
$sql .= "SELECT 2";
$sql .= "SELECT 3";
...
$result = $conn->query($sql);
while($row = $result->fetch_assoc()) {
echo $anzahlpositive1 ;
echo $anzahlpositive2 ;
echo $anzahlpositive3 ;
....
}
select count(max720) AS ...
union all
select count(max720) AS ...
You can use as many unions as you want, read the difference between union and union all, union will discard duplicates.
Related
<?php
$query1 = "CREATE VIEW current_rankings AS SELECT * FROM main_table WHERE date = X";
$query2 = "CREATE VIEW previous_rankings AS SELECT rank FROM main_table WHERE date = date_sub('X', INTERVAL 1 MONTH)";
$query3 = "CREATE VIEW final_output AS SELECT current_rankings.player, current_rankings.rank as current_rank LEFT JOIN previous_rankings.rank as prev_rank
ON (current_rankings.player = previous_rankings.player)";
$query4 = "SELECT *, #rank_change = prev_rank - current_rank as rank_change from final_output";
$result = mysql_query($query4) or die(mysql_error());
while($row = mysql_fetch_array($result)) {
echo $row['player']. $row['current_rank']. $row['prev_rank']. $row['rank_change'];
}
?>
All the queries work independently but am really struggling putting all the pieces together in one single result so I can use it with mysql_fetch_array.
I've tried to create views as well as temporary tables but each time it either says table does not exist or return an empty fetch array loop...logic is there but syntax is messed up I think as it's the 1st time I had to deal with multiple queries I need to merge all together. Looking forward to some support. Many thanks.
Thanks to php.net I've come up with a solution : you have to use (mysqli_multi_query($link, $query)) to run multiple concatenated queries.
/* create sql connection*/
$link = mysqli_connect("server", "user", "password", "database");
$query = "SQL STATEMENTS;"; /* first query : Notice the 2 semicolons at the end ! */
$query .= "SQL STATEMENTS;"; /* Notice the dot before = and the 2 semicolons at the end ! */
$query .= "SQL STATEMENTS;"; /* Notice the dot before = and the 2 semicolons at the end ! */
$query .= "SQL STATEMENTS"; /* last query : Notice the dot before = at the end ! */
/* Execute queries */
if (mysqli_multi_query($link, $query)) {
do {
/* store first result set */
if ($result = mysqli_store_result($link)) {
while ($row = mysqli_fetch_array($result))
/* print your results */
{
echo $row['column1'];
echo $row['column2'];
}
mysqli_free_result($result);
}
} while (mysqli_next_result($link));
}
EDIT - The solution above works if you really want to do one big query but it's also possible to execute as many queries as you wish and execute them separately.
$query1 = "Create temporary table A select c1 from t1";
$result1 = mysqli_query($link, $query1) or die(mysqli_error());
$query2 = "select c1 from A";
$result2 = mysqli_query($link, $query2) or die(mysqli_error());
while($row = mysqli_fetch_array($result2)) {
echo $row['c1'];
}
It seems you are not executing $query1 - $query3. You have just skipped to $query4 which won't work if the others have not been executed first.
Also
$query4 = "SELECT *, #rank_change = prev_rank - current_rank as rank_change from final_output";
should probably be
$query4 = "SELECT *, #rank_change := prev_rank - current_rank as rank_change from final_output";
or else the value of rank_change will just be a boolean, true if #rank_change is equal to (prev_rank - current_rank), false if it is not. But do you need #rank_change at all? Will you use it in a subsequent query? Maybe you can remove it altogether.
Even better, you could just combine all the queries into one like this:
SELECT
curr.player,
curr.rank AS current_rank,
#rank_change := prev.rank - curr.rank AS rank_change
FROM
main_table AS curr
LEFT JOIN main_table AS prev
ON curr.player = prev.player
WHERE
curr.date = X
AND prev.date = date_sub('X', INTERVAL 1 MONTH)
You should concatenate them:
<?php
$query = "CREATE VIEW current_rankings AS SELECT * FROM main_table WHERE date = X";
$query .= " CREATE VIEW previous_rankings AS SELECT rank FROM main_table WHERE date = date_sub('X', INTERVAL 1 MONTH)";
$query .= " CREATE VIEW final_output AS SELECT current_rankings.player, current_rankings.rank as current_rank LEFT JOIN previous_rankings.rank as prev_rank
ON (current_rankings.player = previous_rankings.player)";
$query .= " SELECT *, #rank_change = prev_rank - current_rank as rank_change from final_output";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)) {
echo $row['player']. $row['current_rank']. $row['prev_rank']. $row['rank_change'];
}
?>
How can I do something like this:
$query = "SELECT a,b FROM c ORDER BY a";
$query1 = "SELECT a,b FROM '".$query."' WHERE a='".$number."'";
Thank you very much
REAL CASE
$query2 = "SELECT numero,spartenza,sarrivo,opartenza,oarrivo FROM treni ORDER BY opartenza";
$query1 = "SELECT spartenza,sarrivo,opartenza,oarrivo,TIMEDIFF(oarrivo,opartenza) FROM (".$query2.") AS 'ordinata' WHERE numero = '".$id_treno."' ORDER BY opartenza";
Wrap it in parenthesis:
$query1 = "SELECT a,b FROM (".$query.") AS `alias` WHERE a='".$number."'";
Subqueries like this need to be aliased.
MySQl Subquery Documentation
REAL CASE
$query = "SELECT spartenza,sarrivo,opartenza,oarrivo,TIMEDIFF(oarrivo,opartenza) FROM treni WHERE numero = '".$id_treno."' ORDER BY opartenza";
You do not need a subquery at all for this. You can ORDER BY a column that you aren't selecting. One suggestion though would be to alias your TIMEDIFF function like this sothat it will be easier to retrieve.
$query = "SELECT spartenza,sarrivo,opartenza,oarrivo,TIMEDIFF(oarrivo,opartenza) AS `timediff_alias` FROM treni WHERE numero = '".$id_treno."' ORDER BY opartenza";
The code I have below joins 5 tables and then is suppose to sort by date_timed_added. The query worked perfectly if i only join 4 tables. For some reason after the 4th table, its giving me issues. The issue is that it sorts and displays the 5th table first and then the rest follow. How can i fix it so that it sorts date_time_added properly by querying all the other tables?
//$sid is a variable that is drawn from DB
$sql = "select `client_visit`.`visit_id`, `client_visit`.
`why_visit`, `client_visit`.`date_time_added`, `client_visit`.
`just_date`, `client_visit`.`type` from `client_visit` where
`client_visit`.`system_id` = '$sid' and `client_visit`.
`added_by` = '$sid'
UNION
select `client_notes`.`note_id`, `client_notes`.`note_name`,
`client_notes`.`date_time_added`, `client_notes`.`just_date`
, `client_notes`.`type` from `client_notes` where `client_notes`.
`added_by` = '$sid'
UNION
select `client_conditions`.`med_id`, `client_conditions`.`med_name`,
`client_conditions`.`date_time_added`, `client_conditions`.`just_date`,
`client_conditions`.`type` from `client_conditions` where
`client_conditions`.`system_id` = '$sid' and `client_conditions`.
`added_by` = '$sid'
UNION
select `client_stats`.`stat_test_id`, `client_stats`.`stat_why`,
`client_stats`.`date_time_added`, `client_stats`.`just_date`,
`client_stats`.`type`
from `client_stats` where `client_stats`.`system_id` = '$sid'
and `client_stats`.`added_by` = '$sid'
UNION
select `client_documents`.`doc_id`, `client_documents`.`doc_name`,
`client_documents`.`date_time_added`, `client_documents`.`just_date`,
`client_documents`.`type` from `client_documents` where `client_documents`.
`system_id` = '$sid' and `client_documents`.`added_by` = '$sid'
ORDER BY `date_time_added` DESC LIMIT $startrow, 20";
$query = mysql_query($sql) or die ("Error: ".mysql_error());
$result = mysql_query($sql);
if ($result == "")
{
echo "";
}
echo "";
$rows = mysql_num_rows($result);
if($rows == 0)
{
}
elseif($rows > 0)
{
while($row = mysql_fetch_array($query))
{
//Just using these two variables i can display the same row info
//for all the other tables
$stuffid = htmlspecialchars($row['visit_id']);
$title = htmlspecialchars($row['why_visit');
}
}
}
As per the MySQL docs: http://dev.mysql.com/doc/refman/5.0/en/union.html
If you want to order the ENTIRE result set, the ORDER BY clause must be placed on the LAST query in the UNION, with each query being bracketed.
(SELECT ...)
UNION
(SELECT ...)
ORDER BY ...
sth like this should do.
SELECT Tbl1.field1
FROM ( SELECT field1 FROM table1
UNION
SELECT field1 FROM table2
) Tbl1
ORDER BY Tbl1.field1
<?php
$query1 = "CREATE VIEW current_rankings AS SELECT * FROM main_table WHERE date = X";
$query2 = "CREATE VIEW previous_rankings AS SELECT rank FROM main_table WHERE date = date_sub('X', INTERVAL 1 MONTH)";
$query3 = "CREATE VIEW final_output AS SELECT current_rankings.player, current_rankings.rank as current_rank LEFT JOIN previous_rankings.rank as prev_rank
ON (current_rankings.player = previous_rankings.player)";
$query4 = "SELECT *, #rank_change = prev_rank - current_rank as rank_change from final_output";
$result = mysql_query($query4) or die(mysql_error());
while($row = mysql_fetch_array($result)) {
echo $row['player']. $row['current_rank']. $row['prev_rank']. $row['rank_change'];
}
?>
All the queries work independently but am really struggling putting all the pieces together in one single result so I can use it with mysql_fetch_array.
I've tried to create views as well as temporary tables but each time it either says table does not exist or return an empty fetch array loop...logic is there but syntax is messed up I think as it's the 1st time I had to deal with multiple queries I need to merge all together. Looking forward to some support. Many thanks.
Thanks to php.net I've come up with a solution : you have to use (mysqli_multi_query($link, $query)) to run multiple concatenated queries.
/* create sql connection*/
$link = mysqli_connect("server", "user", "password", "database");
$query = "SQL STATEMENTS;"; /* first query : Notice the 2 semicolons at the end ! */
$query .= "SQL STATEMENTS;"; /* Notice the dot before = and the 2 semicolons at the end ! */
$query .= "SQL STATEMENTS;"; /* Notice the dot before = and the 2 semicolons at the end ! */
$query .= "SQL STATEMENTS"; /* last query : Notice the dot before = at the end ! */
/* Execute queries */
if (mysqli_multi_query($link, $query)) {
do {
/* store first result set */
if ($result = mysqli_store_result($link)) {
while ($row = mysqli_fetch_array($result))
/* print your results */
{
echo $row['column1'];
echo $row['column2'];
}
mysqli_free_result($result);
}
} while (mysqli_next_result($link));
}
EDIT - The solution above works if you really want to do one big query but it's also possible to execute as many queries as you wish and execute them separately.
$query1 = "Create temporary table A select c1 from t1";
$result1 = mysqli_query($link, $query1) or die(mysqli_error());
$query2 = "select c1 from A";
$result2 = mysqli_query($link, $query2) or die(mysqli_error());
while($row = mysqli_fetch_array($result2)) {
echo $row['c1'];
}
It seems you are not executing $query1 - $query3. You have just skipped to $query4 which won't work if the others have not been executed first.
Also
$query4 = "SELECT *, #rank_change = prev_rank - current_rank as rank_change from final_output";
should probably be
$query4 = "SELECT *, #rank_change := prev_rank - current_rank as rank_change from final_output";
or else the value of rank_change will just be a boolean, true if #rank_change is equal to (prev_rank - current_rank), false if it is not. But do you need #rank_change at all? Will you use it in a subsequent query? Maybe you can remove it altogether.
Even better, you could just combine all the queries into one like this:
SELECT
curr.player,
curr.rank AS current_rank,
#rank_change := prev.rank - curr.rank AS rank_change
FROM
main_table AS curr
LEFT JOIN main_table AS prev
ON curr.player = prev.player
WHERE
curr.date = X
AND prev.date = date_sub('X', INTERVAL 1 MONTH)
You should concatenate them:
<?php
$query = "CREATE VIEW current_rankings AS SELECT * FROM main_table WHERE date = X";
$query .= " CREATE VIEW previous_rankings AS SELECT rank FROM main_table WHERE date = date_sub('X', INTERVAL 1 MONTH)";
$query .= " CREATE VIEW final_output AS SELECT current_rankings.player, current_rankings.rank as current_rank LEFT JOIN previous_rankings.rank as prev_rank
ON (current_rankings.player = previous_rankings.player)";
$query .= " SELECT *, #rank_change = prev_rank - current_rank as rank_change from final_output";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)) {
echo $row['player']. $row['current_rank']. $row['prev_rank']. $row['rank_change'];
}
?>
My page displays an image, and I want to display the previous and next image that is relevant to the current one. At the moment I run the same query 3x and modify the "where" statement with =, >, <.
It works but I feel there must be a better way to do this.
The image id's are not 1,2,3,4,5. and could be 1,2,10,20,21 etc. But if it is much more efficient I am willing to change this.
mysql_select_db("database", $conPro);
$currentid = mysql_real_escape_string($_GET['currentid']);
$query ="SELECT * FROM database WHERE id ='".$currentid."' LIMIT 1 ";
$result = mysql_query($query,$conPro) or die(mysql_error());
$affected_rows = mysql_num_rows($result);
if ($affected_rows==1)
{
$row = mysql_fetch_array($result)or die ('error:' . mysql_error());
$current_id = $row['id'];
$current_header = $row['title'];
$current_description =$row['desc'];
$current_image = "http://".$row['img'];
$current_url = "http://".$row['id']."/".$db_title."/";
$current_thumb = "http://".$row['cloud'];
}
mysql_select_db("database", $conPro);
$query ="SELECT * FROM database WHERE id <'".$currentid."' ORDER BY id DESC LIMIT 1 ";
$result = mysql_query($query,$conPro) or die(mysql_error());
$affected_rows = mysql_num_rows($result);
if ($affected_rows==1)
{
$row = mysql_fetch_array($result)or die ('error:' . mysql_error());
$previous_id = $row['id'];
$previous_header = $row['title'];
$previous_description =$row['desc'];
$previous_image = "http://".$row['img'];
$previous_url = "http://".$row['id']."/".$db_title."/";
$previous_thumb = "http://".$row['cloud'];
}else{
$previous_none = "true"; //no rows found
}
mysql_select_db("database", $conPro);
$query ="SELECT * FROM database WHERE id >'".$currentid."' ORDER BY id ASC LIMIT 1 ";
$result = mysql_query($query,$conPro) or die(mysql_error());
$affected_rows = mysql_num_rows($result);
if ($affected_rows==1)
{
$row = mysql_fetch_array($result)or die ('error:' . mysql_error());
$next_id = $row['id'];
$next_header = $row['title'];
$next_description =$row['desc'];
$next_image = "http://".$row['img'];
$next_url = "http://".$row['id']."/".$db_title."/";
$next_thumb = "http://".$row['cloud'];
}else{
$next_none = "true"; //no rows found
}
mysql_close($conPro);
Thank you for your time
You don't have to do select_db each time. Once you 'select' a db, it stays selected until you select something else.
You can't really get away from doing two separate queries to get the next/previous images, but you can fake it by using a union query:
(SELECT 'next' AS position, ...
FROM yourtable
WHERE (id > $currentid)
ORDER BY id ASC
LIMIT 1)
UNION
(SELECT 'prev' AS position, ...
FROM yourtable
WHERE (id < $currentid)
ORDER BY id DESC
LIMIT 1)
This would return two rows, containing a pseudofield named 'position' which will allow you to easily identify which row is the 'next' record, and which is the 'previous' one. Note that the brackets are required so that the 'order by' clauses apply to the individual queries. Without, mysql will take the order by clause from the last query in the union sequence and apply it to the full union results.
You can get the "previous" one first WHERE id <'".$currentid."' ORDER BY id DESC, and then query for two "above" it: SELECT * FROM database WHERE id >= '".$currentid."' ORDER BY id ASC then it takes only two queries instead of three.