MySQL fastest way to query rows - php

My problem is that i don't yet have a good server to test this on but i'd like to know if it faster to use:
$sqlgetg = "SELECT assignments.id FROM assignments LEFT JOIN userassignments ON assignments.id = userassignments.assignmentid WHERE userassignments.userid = '" . $row['id'] . "' AND userassignments.assignmentid = '" . $assignmentid . "'";
or
$sqlgetg = "SELECT NULL FROM assignments LEFT JOIN userassignments ON assignments.id = userassignments.assignmentid WHERE userassignments.userid = '" . $row['id'] . "' AND userassignments.assignmentid = '" . $assignmentid . "'";
Since i have to check if there even is an assigment for the user with assignment id of x? I don't need anything else but this: if(mysqli_num_rows($resultgetg) > 0)? In both cases phpMyAdmin gave me the row number that i wanted. (I checked it with
without WHERE and it still worked.)
EDIT:
I don't know how and why NULL works but it does...

You can select any static value "from" a table if you just want to count the rows returned... SELECT NULL or SELECT 42 or whatever. But both of your strategies are in fact suboptimal, because they require unnecessary work by the server and unnecessary network traffic and unnecessary handling of the result set that you are only planning to discard.
If counting rows is what you want, then actually do that. you should SELECT COUNT(*) AS how_many_rows ... and let the server count the rows and return a single row with a single column ("how_many_rows" -- make up your own alias) containing the count.

Related

SQL MATCH not Matching correctly

I have 3 tables, and i have joined them together, which works fine, it pulls the information. One of the tables as an array within a column, on every row like:
["Pets","Schools","Shops"]
I need, while selecting, the query to pull out when a MATCH AGAINST a var. Here is my code:
$searchRefine = '';
foreach( $refineAmen as $key => $val) {
$searchRefine = $searchRefine . " MATCH(pa.Property_Amenities) AGAINST ('".$val."' IN BOOLEAN MODE) OR ";
}
The above takes each var from the array from the row / column, and adds it to a sub-query string.
$searchRefine = substr($searchRefine, 0, -3);
The above takes out the last 3 (or the word 'OR') at the end as its not needed
$detail = "SELECT p.*, pi.*, pa.* FROM tbl_property p LEFT join tbl_property_images pi on p.Property_Id = pi.Property_Id LEFT join tbl_property_amenities pa on pi.Property_Id = pa.Property_Id WHERE (p.Property_Postcode='" . $_POST['cust_id'] . "' OR p.Property_City Like '%" . $_POST['cust_id'] . "%') AND ( " . $searchRefine. " ) GROUP BY pi.Property_Id";
The above takes the sub strings and adds it to the final for firing. I do not get any errors.
The issue is, it does not pull the records with any of these key works within the row, just One. I have tried a number of combinations of AND or OR, so the query understands. But still no luck. Any someone look at this, and see if they can see what I have done wrong.
Thanks
You should normalize your database structure instead of storing multiple values in one column. This way you would not have to compute a sub-query string for fulltext search with MATCH...AGAINST.
Can you show your database structure?
Beware of SQL injection. Once your query is working you should alter it to escape client data oder use prepared statements.

MySQLi query skipping first 5 rows

I have the following MySqli query:
$run = 0;
$result = $conn->query("SELECT title, author,i.isbn13, i.sku, quantity, weight, listed_price
from book
LEFT JOIN inventory i on book.isbn13 = i.isbn13
where quantity > 0 and i.isbn13 like '978%' limit $run, 5");
Which I then run through Amazon's API to return XML Data. I then parse that to update my table with:
$conn->query("update book set author = '" . addslashes($amazonResult['Author']) . "', title ='" . addslashes($amazonResult['Title']) . "',
edition='" . addslashes($amazonResult['Edition']) . "',
weight='" . $amazonResult['Weight'] . "', publisher='" . addslashes($amazonResult['Publisher']) . "', binding='" . $amazonResult['Binding'] . "',
pub_date='" . $amazonResult['PublishDate'] . "', listed_price = '" .$amazonResult['ListPrice'] . "'
where isbn13 = '" . $amazonResult['isbn'] . "'");
Update $run:
$run=$run+5;
and have it loop through again. Yet my output skips the first 5 rows in the table and returns the next 5. Also, after running about 20 or so records, it skips 5 again. The rows that it processes, it does correctly, which I verify by an echo of the query. When I use the query in Navicat, replace $run with 0, everything looks fine, the first 5 rows are returned.
Any idea what I did wrong or how I can fix this? I have never encountered this in the past and use almost the same query for different reports.
If you want to return a specific range of records, make sure to also add an order by clause. MySQL might change the order of rows between queries.
Another, maybe even more plausible cause, is that a query can sometimes fail. For instance, if one of the fields contains an invalid character, it might break your query, return false instead of a mysqli query result, and therefor fail to output anything.
You are using addslashes to escape strings, but that's not the proper way to do it. You can use mysqli_real_escape_string, or even better: use parameterized queries (prepared statements).

Trying to search one table using the value from another table

I am trying to program a lookup tool in PHP with SQL database.
$sql="SELECT
ID,
switch,
vlan,
circuit_id
FROM vlan
WHERE switch
LIKE LOWER('%" . $name . "%') OR vlan='" . $name ."'
ORDER BY vlan";
then further down I have this to put the results into variables:
while($row=mysql_fetch_array($result)){
$switch =$row['switch'];
$vlan=$row['vlan'];
$circuitID=$row['circuit_id'];
$ID=$row['ID'];
What I am wanting to do is take the switch reply and use that to do another query on a different table named router and return that information.
I have been searching for a few days and all of my searches ended up here but didnt seem to quite fit. I apreciate any help you can give.
UPDATE
With some great answers I finally got this to work. Here is how I did it. Thanks for the help.
while($row=mysql_fetch_assoc($result)){
$switch =$row['switch'];
$vlan=$row['vlan'];
$circuitID=$row['circuit_id'];
$ID=$row['ID'];
$sql2 = "SELECT IPAddress FROM router
WHERE switch LIKE '%".$switch."%'
LIMIT 1";
$result2 = mysql_query($sql2);
$row2=mysql_fetch_array($result2);
$IPAddress = $row2['IPAddress'];
Probably real ugly to the more experienced but it works. Thanks again.
It would be highly inefficient to run a secondary lookup query in a loop.
What you want is a simple JOIN between your two tables based on the switch field. What this will do is bring the linked rows in your router table alongside the rows in your vlan table where values in the switch column match up:
$sql = '
SELECT a.id, a.switch, a.vlan, a.circuit_id, b.ipaddress
FROM vlan a
JOIN router b ON a.switch = b.switch
WHERE a.switch LIKE "%' . strtolower($name) . '%" OR vlan = "' . $name . '"
ORDER BY a.vlan';
Then in your same fetch loop, you'll be able to access the linked values from your router table without having to run extra database calls:
while($row=mysql_fetch_array($result)){
$switch =$row['switch'];
$vlan=$row['vlan'];
$circuitID=$row['circuit_id'];
$ID=$row['ID'];
$ipaddress = $row['ipaddress'];
}
How many results do you expect? If there's more than one result, you might need to point which row exactly you want to take. Since it's fetch_array, your $row['switch'] or $switch value is still an array. var_dump it for keys and use the key, i.e.
SELECT `col` FROM `router` WHERE `switch` = '$switch[1]'

Select SUM() as a variable in a for Loop

I'm trying to generate XML from database and need to gather a specific amount of data based on the average from a column. This can vary from anywhere between 5 to 30 queries for the $numItems variable.
I need to execute a for loop and assign the column name in the SUM($variable) but I'm not getting any data (but no errors either).
Here is my code:
for ($t = 1; $t <= $numItems; $t++){
$query = mysql_fetch_assoc(mysql_query("SELECT SUM(column'".$t."') AS value_sum FROM scoring WHERE ID='" . $userID . "' AND name ='" . $name . "'"));
$q = $query['value_sum'] / $totalUsers;
echo "<output".$t.">" . $q . "</output".$t.">\n";
}
The problem is assigning the SUM(column1) variable name for the column I'm getting data from, when I write the queries individually it works, but assigning the variable within the statement is causing a problem. Can any one give me any pointers?
Thanks in advance.
It looks like you might have extra single quotes in your query. I think it should be:
"SELECT SUM(column".$t.")..."
You should also consider doing a single select. Doing multiple database calls inside a for loop will be a huge performance problem. You could write a single select like this:
"SELECT SUM(column1), SUM(column2), SUM(column3),..."
Looks like bad escaping/concatenation around the column name...
"SELECT SUM(column{$t}) AS value_sum FROM scoring WHERE ID='{$userID}' AND name ='{$name}'"
Is that what you want?
Also use PDO!

(MySQL)Need to get match scores from multiple tables and sort by the sum of their scores

I need to get the MATCH AGAINST scores from multiple tables with a common key and combine their sums. The goal in the end is to create a search algorithm that will return rows with matching group_IDs. I have built a mysql query that has yet to run without error.
In case you want to know, this is the specific error:
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL
result resource
These are the tables I wish to search:
table: jn_groups
group_ID, name
table: jn_chat
chat_ID, group_ID, name
table: jn_events
event_ID, group_ID, title, description
My current query looks like this:
SELECT
g.group_ID AS group_ID,
g.name AS name,
SUM(gscore + cscore + escore) AS score,
MATCH(g.name) AGAINST (" . $query . "') AS gscore,
MATCH(c.name) AGAINST (" . $query . "') AS cscore,
MATCH(e.title,e.description) AGAINST (" . $query . "') AS escore
FROM jn_groups g
LEFT JOIN jn_chat c ON g.group_ID = c.group_ID
LEFT JOIN jn_events e ON g.group_ID = e.group_ID
WHERE
MATCH(g.name) AGAINST (" . $query . "')
OR MATCH(c.name) AGAINST (" . $query . "')
OR MATCH(e.title,e.description) AGAINST (" . $query . "')
ORDER BY score
Any help making a query similar to that run would be greatly appreciated!
Two things which could be the reason for breaking this query:
variable $query
All your AGAINST-operators end with "', but start only with ". Make sure $query contains
valid data and
start with an '.
Summate the partial results
Your SUM won't work, because it doesn't know gscore, cscore and escore. It will look for field names instead. You can change this part of your statement like this (ofc replace hello world with your desired search term):
....
SUM(
(MATCH(g.name) AGAINST ('hello world'))
+ (MATCH(c.name) AGAINST ('hello world'))
+ (MATCH(e.title,e.description) AGAINST ('hello world'))
) AS score,
....
Two advices:
Try running the query against your database with a SQL
tool first (p.e. SQLyog, MySQL Workbench, phpMyAdmin or similar), to see if it is working like you want it to. There are a few other possibilities how to break this (p.e. no or wrong fulltext index definition, wrong field names and such), so you have better control about whats going wrong.
Be careful when using reserved variables like NAME in field names. Either escape them properly or - in my eyes better - avoid them.

Categories