I am New to php and programming as well.
I have a variable in an SQL query-based while loop. Below
switch ($command) {
case "country":
$statement = "SELECT w_id,w_name FROM wards ORDER BY w_id ASC";
$dt = mysqli_query($conn, $statement);
while ($result = mysqli_fetch_array($dt)) {
echo $result1 = "<option value=" . $result['w_id'] . ">" . $result['w_name'] . "</option>";
}
break;
}
exit();
The loop works just fine butthe variable contains duplicate strings.
How do I prevent duplicate row variables echoing in my while loop with PHP?
That means you have duplicate rows in your DB, if you'd like to retrieve unique values, you could try a "group by" statement.
SELECT w_id, w_name FROM wards GROUP BY w_name, w_id ORDER BY w_id ASC
It's a good practice indenting your code so you don't get confused in later reviews :)
Change your sql query by using distinct keyword.
SELECT DISTINCT w_id, w_name FROM wards ORDER BY w_id ASC
This will prevent fetching duplicate rows from your DB.
Please see the documentation: https://www.w3schools.com/sql/sql_distinct.asp
Related
I have a query that I would really appreciate any bit of help on.
I have a first query that selects the job_types in one table (26 results). These job_type names all relate to a separate table that is the same name as them. Then, I need to use this result (the list of job_types) to call a new query on all the related job_type tables - looping through the results from the first query, inserting them in to the second query, and I am trying to UNION the results and output them into a table. But I'm stuck with the loop. My code so far is:
$sql = "";
$union = "";
$tables = [];
$q = "SELECT DISTINCT job_table
FROM job_type
WHERE job_type NOT IN (26, 28) AND status = 1";
$tables[] = $conn->query($q);
print_r($tables);
/*while ($table = $tables->fetch_assoc()) {
$sql .= "SELECT
DATE(call_time) AS `date`,
COUNT(*) AS `sub_total`,
'$table->job_table' AS `table`
FROM '$table->job_table'
WHERE table.show IS TRUE AND call_time BETWEEN $startDate AND $endDate
AND table.processing_complete IS TRUE
GROUP BY `date`";
}*/
foreach ($tables AS $table) {
$sql .= $union . "SELECT
DATE(call_time) AS `date`,
COUNT(*) AS `sub_total`,
'$table' AS `table`
FROM '$table'
WHERE table.show IS TRUE AND call_time BETWEEN $startDate AND $endDate
AND table.processing_complete IS TRUE
GROUP BY `date`";
$union = " UNION ";
}
I know I need to put in a loop, in order to union the tables and run through them until the final one, so the WHILE loop is something I was trying out, as is the FOREACH loop. I'm only learning (slowly) PHP and would much appreciate any assistance.
EDIT
I have added the following code to the end to try and get it to display.
$results = $conn->query($sql);
}
while ($row = $results->fetch_assoc()) {
echo"<TABLE><TR><TD>". $row["date"]. "</TD>";
echo"<TD>". $row["sub_total"]. "</TD>";
echo"<TD>". $row["table"] . "</TD></TR>";
}
However, then I run it, I am returning the following error - 'Catchable fatal error: Object of class mysqli_result could not be converted to string' on the '$table' AS table line.
The part you put in comments was the better attempt, so I will focus on that code block.
Some issues:
The query method returns a result object. You should not assign it to $tables[], which would make $tables an array with one result object. Just assign the result to $tables.
The fetch_assoc method makes your records available as associative records, so you should not use the object notation $table->, but brackets: $table[ ... ].
The FROM clause in SQL should not be followed by something in quotes, but by the name itself, so don't put single quotes there
When you embed expressions in a double quoted string, you need to wrap them in braces, like {$table[...]}. Without those braces you can only embed atomic variables, like $startDate.
In MySql SQL dates must be quoted (I assume $startDate and $endDate are strings)
In SQL the IS operator is really intended in combination with NULL, not with another value. What's more, checking equality with TRUE is often overkill, as you could just test the expression on the left of the equality
To join the different SQL snippets with UNION, you could first collect them in an array, and then apply implode to that. Also: UNION ALL has better performance, and makes no difference in your case.
Corrected code:
// *** query method returns a result object, not an array:
$tables = $conn->query($q);
while ($table = $tables->fetch_assoc()) {
// *** Use {$ ... } notation, with bracket access, not '->'.
// *** Quote dates. Do not quote tables. Omit "IS TRUE".
// *** Collect into array. The `UNION` can be added later.
$sql[] = "
SELECT
DATE(call_start_time) AS `date`,
COUNT(*) AS `sub_total`,
'{$table[job_processing_table]}' AS `table`
FROM {$table[job_processing_table]}
WHERE table.show
AND call_start_time BETWEEN '$startDate' AND '$endDate'
AND table.processing_complete
GROUP BY `date`";
}
// *** Add UNION:
$sql = implode(" UNION ALL ", $sql)
A little help would be lifesaving. I have an sql query that works in phpMyAdmin and gives me the result i need.
When i build this query into a php statement i cant seem to access the result (an integer)
I literally need to echo the value, so i need to output for exanmple " your number is" result.
here is my query:
$sqlstatement = "SELECT (SELECT `embark` FROM info ORDER BY `index_no` DESC LIMIT 1)-(SELECT `embark` FROM info ORDER BY `index_no` ASC LIMIT 1)";
$sql_result = mysqli_query($connection, $sqlstatement) or die (" Couldn't execute the SQL calculate disembark statement********");
If anyone can help i would really appreciate it
Scott
Fetch the row of results into an array, and then access the element of the array to echo it.
$row = mysqli_fetch_array($sql_result);
if ($row) {
echo "Your number is " . $row[0];
}
I used mysqli_fetch_array because you didn't assign an alias to the result column.
BTW, you can simplify your query to:
SELECT MAX(index_no)-MIN(index_no) FROM info
I'm trying to search MYSQL database using multiple Dropdown lists on my page.
However, there is a small twist in this search function.
Basically, I need to make sure All the criteria (all the multiple select dropdonw values) match the items and if they do match then show the result!
At the moment, my code shows the results even if one of the dropdown values match the items which is not what i am trying to do.
This is my code:
$searchList = "";
$clause = " WHERE ";//Initial clause
$sql="SELECT *
FROM `product_details`
INNER JOIN `ATTRIBUTES` ON product_details.id=ATTRIBUTES.id";//Query stub
if(isset($_POST['keyword']) && !empty($_POST['keyword'])){
foreach($_POST['keyword'] as $c){
if(!empty($c)){
$currentproduct = $_POST['product'];
$cat = $_POST['cat'];
##NOPE##$sql .= $clause."`".$c."` LIKE '%{$c}%'";
$sql .= $clause . " (ATTRIBUTES.attr LIKE BINARY '$c') AND ATTRIBUTES.sub_cat_name='$currentproduct'";
$clause = " OR ";//Change to OR after 1st WHERE
}
}
$sql .= " GROUP BY product_details.id";
//print "SQL Query: $sql<br />"; //<-- Debug SQl syntax.
// Run query outside of foreach loop so it only runs one time.
$query = mysqli_query($db_conx, $sql);
I even tried to remove the isset and did if(!empty($_POST['keyword'])){ but i still get results even if one of the dropdown lists values match the items credentials.
I'm not sure what I am doing wrong here as I thought using if(!empty($_POST['keyword'])){ should solve this issue but it hasn't.
Could someone please advise on this issue?
any help would be appreciated.
EDIT: I changed the CODE to the following and it doesn't display anything:
$clause = " WHERE ";//Initial clause
$sql="SELECT *
FROM `product_details`
INNER JOIN `ATTRIBUTES` ON product_details.id=ATTRIBUTES.id";//Query stub
$currentproduct = $_POST['product'];
$cat = $_POST['cat'];
if(!empty($_POST['keyword'])){
foreach($_POST['keyword'] as $c){
if(!empty($c)){
##NOPE##$sql .= $clause."`".$c."` LIKE '%{$c}%'";
$sql .= $clause . " (ATTRIBUTES.attr LIKE BINARY '$c') AND ATTRIBUTES.sub_cat_name='$currentproduct'";
$clause = " AND ";//Change to OR after 1st WHERE
}
}
$sql .= " GROUP BY product_details.id";
//print "SQL Query: $sql<br />"; //<-- Debug SQl syntax.
// Run query outside of foreach loop so it only runs one time.
$query = mysqli_query($db_conx, $sql);
//var_dump($query); //<-- Debug query results.
// Check that the query ran fine.
if (!$query) {
print "ERROR: " . mysqli_error($db_conx);
}
$clause = " OR ";//Change to OR after 1st WHERE
The above OR operator will cause your where criteria to select a record even if 1 keyword matches the attr field. Change it to " AND " to expect all keywords to apply.
Furthermore, ... AND ATTRIBUTES.sub_cat_name='$currentproduct'" criterion seems to apply to all keywords, so this criterion should be added once, not at every iteration of the loop. $currentproduct = $_POST['product']; row should also be moved in fron of the loop.
EDIT: to reflect to changing the opreator to AND and not having any rows returned.
...ATTRIBUTES.attr LIKE BINARY '$c'...
If there are no wildcards in $c, then the above criterion will require the word to match the attr field as if = operator had been used, which is unlikely to happen. Wildcards must be included in the search: '%$c%'
Plus some protection from sql injection would also be nice.
EDIT2:
If each attribue is stored in its own record, then it complicates things a little bit, since the where criteria is evaluated against a single record, not a collection of them.
I'll give you a sample select command, but you will have to incorporate it into your php code.
select product_details.* FROM product_details INNER JOIN
(select product_details.id, count(ATTRIBUTES.id) as total
FROM `product_details`
INNER JOIN `ATTRIBUTES` ON product_details.id=ATTRIBUTES.id
WHERE ATTRIBUTES.attr in (...)
GROUP BY product_details.id
HAVING total=...) as t
on t.id=product_details.id
The subquery counts how many attributes were matched for a product and eliminates those, where the count does not equal to the number of parameters submitted via the form. The outer query gets the product details for those, where the count matched.
For the ... in the in() clause you need to provide a comma separated, ' enclosed list of the keywords, like: "'computer', 'apple'". Use implode() function in php and sztring concatenation to get the results.
For the ... in the having clause substitute the number of keywords in the $_POST['keyword'] array (you should check in the code if it's an array or just a single value, though).
Still, you should consider the impact of sql injection on your code.
The code below searches my mysql database and comes back with postcodes like IG6,RM11,RM8,RM4,RM2,RM6,RM7,RM1,RM5 and a distance using a stored procedure. (All ok)
PROBLEM: With these results, I want to search another table in same database that may have job information with those Postcodes (probably using LIKE).
What's the best way to get this working? I have tried many examples (implode, arrays, etc)
Is one connection to database correct? How do I query the variable as it does come back with 2 columns, postcode and Distance. Should I split in an array (how?)
END PRODUCT: HGV Driver RM5, Cleaner RM5, Teacher RM5
(SELECT title FROM jobinfo WHERE location IN results from other query);
<?php
include ("conn.php");
$first="RM5";
$result = mysql_query("select outcode, GetDistance(Lat, Lon, (SELECT Lat from postcodes where outcode = '$first' limit 1),(SELECT Lon from postcodes where outcode = '$first' limit 1)) as Distance from postcodes having Distance < 3 order by Distance DESC;");
while($row = mysql_fetch_array($result))
{
echo ($row['outcode']) ;
}
// This returns postcodes
$resultb = mysql_query("SELECT title FROM jobinfo WHERE location IN ($results[outcode]) ");
while($row = mysql_fetch_array($resultb))
{
echo ($row['title']) ;
}
mysql_close($con);
?>
Please help.....any reference to join table needs full explanation as all so far don't help!
First Prepare the output into the clause:
in the first while loop:
while($row = mysql_fetch_array($result))
{
$array[] = $row['outcode'] ;
}
Then prepare the array for the IN clause:
foreach ($array as $a) {$clause.= "'$a',";}
$clause=substr($clause,0,-1)
Finally use the clause for the IN statement:
$resultb = mysql_query("SELECT title FROM jobinfo WHERE location IN ($clause) "
===== EDIT === LIKE statement
For like.. you need multiple like statement OR together.. Using SQL LIKE and IN together
Change the prepare clause code to this:
foreach ($array as $a) {$clause.= " location LIKE '%$a%' OR";}
$clause=substr($clause,0,-3)
AND the sql becomes:
$resultb = mysql_query("SELECT title FROM jobinfo WHERE $clause ");
Of course you will want to addin some more error checking.. think of the possible injection.
I think you're trying to do something like this answer MySQL LIKE IN()?
Also, please use parametrized queries How can I prevent SQL injection in PHP?
I have a table with 4 record.
Records: 1) arup Sarma
2) Mitali Sarma
3) Nisha
4) haren Sarma
And I used the below SQL statement to get records from a search box.
$sql = "SELECT id,name FROM ".user_table." WHERE name LIKE '%$q' LIMIT 5";
But this retrieve all records from the table. Even if I type a non-existence word (eg.: hgasd or anything), it shows all the 4 record above. Where is the problem ? plz any advice..
This is my full code:
$q = ucwords(addslashes($_POST['q']));
$sql = "SELECT id,name FROM ".user_table." WHERE name LIKE '%".$q."' LIMIT 5";
$rsd = mysql_query($sql);
Your query is fine. Your problem is that $q does not have any value or you are appending the value incorrectly to your query, so you are effectively doing:
"SELECT id,name FROM ".user_table." WHERE name LIKE '%' LIMIT 5";
Use the following code to
A - Prevent SQL-injection
B - Prevent like with an empty $q
//$q = ucwords(addslashes($_POST['q']));
//Addslashes does not work to prevent SQL-injection!
$q = mysql_real_escape_string($_POST['q']);
if (isset($q)) {
$sql = "SELECT id,name FROM user_table WHERE name LIKE '%$q'
ORDER BY id DESC
LIMIT 5 OFFSET 0";
$result = mysql_query($sql);
while ($row = mysql_fetch_row($result)) {
echo "id: ".htmlentities($row['id']);
echo "name: ".htmlentities($row['name']);
}
} else { //$q is empty, handle the error }
A few comments on the code.
If you are not using PDO, but mysql instead, only mysql_real_escape_string will protect you from SQL-injection, nothing else will.
Always surround any $vars you inject into the code with single ' quotes. If you don't the escaping will not work and syntax error will hit you.
You can test an var with isset to see if it's filled.
Why are you concatenating the tablename? Just put the name of the table in the string as usual.
If you only select a few rows, you really need an order by clause so the outcome will not be random, here I've order the newest id, assuming id is an auto_increment field, newer id's will represent newer users.
If you echo data from the database, you need to escape that using htmlentities to prevent XSS security holes.
In mysql, like operator use '$' regex to represent end of any string.. and '%' is for beginning.. so any string will fall under this regex, that's why it returms all records.
Please refer to http://dev.mysql.com/doc/refman/5.0/en/pattern-matching.html once. Hope, this will help you.