This question already has answers here:
How do you use IN clauses with mysqli prepared statements [duplicate]
(3 answers)
Closed 3 years ago.
So my query works on the actual phpmysql server when I manually type in some values but in php I am having some difficulty.
This is my SQL table:
userID | forename | surname | email | age |
------------------------------------------------------------
1 | Jack | Wolf | dj#rave.com | 19 |
2 | Mark | Smith | mark#rave.com | 18 |
3 | Ben | Cas | sex#club.com | 21 |
4 | Jos | Jis | jis#jos.com | 19 |
5 | Luke | Kils | kils#kiss.com | 23 |
------------------------------------------------------------
Basically, I want to pass in some UserID values like this 1,3,5 and it should display:
userID | forename | surname | email | age |
------------------------------------------------------------
1 | Jack | Wolf | dj#rave.com | 19 |
3 | Ben | Cas | sex#club.com | 21 |
5 | Luke | Kils | kils#kiss.com | 23 |
------------------------------------------------------------
The userID values can vary depending on what the user selects so it can be 2 or even 1,2,3,4 or even 1,2,3,4,5
This is my php code:
<?php
require "init.php";
if(!empty($_POST['userID'])){
$userID = $_POST['userID'];
echo $_POST['userID'];
$stmt = "SELECT userID, forename, surname, email, age
FROM users
WHERE userID IN (?)";
$result = $conn-> prepare($stmt);
$result->bind_param('i', $userID);
$result->execute();
$outcome=$result->get_result();
$response = array();
if(($outcome->num_rows)>0){
while($row = $outcome->fetch_assoc()){
$response[] = array
(
"userID" => $row["userID"],
"forename" => $row["forename"],
"surname" => $row["surname"],
"email" => $row["email"],
"age" => $row["age"]
);
}
echo json_encode($response);
}
else{
echo json_encode("None found");
}
}
?>
When I echo $userID = $_POST['userID']; I get 1,2,3 or 1, but then these are not being passed properly to the SELECT STATEMENT. How do I fix it?
Thanks
Something along these lines
...
$userIDs = implode(",",$_POST['userID']); //Array of user ids
$qs = array_fill(0,count($userIds),"?");
$stmt = "SELECT userID, forename, surname, email, age
FROM users
WHERE userID IN (".implode(",",$qs).")";
$bindParams = $userIDs; //Array for the bind parameters
$bindParams = array_unshift($bindParams, "i"); //Prefix with "i"
call_user_func_array([$result, 'bind_param'],$bindParams);
...
The idea is that your statement will need as many "?" as there are user ids since you're binding that many integers.
You'll use call_user_func_array to call the bind_param function with a variable amount of arguments. Note that if you're using PHP 5.6+ you could just do something like: $result->bind_param("i",...$userIDs)
select userName from Table where user_id in (1, 2, 3);.
you can use $_POST['userID'] in this format or convert this format and use it.
Related
Im trying to get data from one table based upon the date in a column from another table. I've tried using an inner join but I can't quite figure out how to make it do what I want. Below is an example. Basicly the numbers in the rules column will referance the rule_id in the infraction rules table. Then output the rule long name in readable text.
user_infractions table
+--------+-----------------+------------------+----------------+
|ban_id | name | username | rules |
+--------+-----------------+------------------+----------------+
| 2 | bob | Bob | 2,7, |
| 7 | dave | dave1 | 3,5, |
+--------+-----------------+------------------+----------------+
infraction_rules table
+--------+-----------------+------------------+----------------+
|rule_id | rule number | short_name | long_name |
+--------+-----------------+------------------+----------------+
| 2 | 1.2.2 | Rule 2 | Rule 2 Long Na |
| 7 | 1.2.7 | Rule 7 | Rule 7 Long Na |
+--------+-----------------+------------------+----------------+
Below is the code im using to try to achieve this
$string = $row['rules']; //data from table as a string
$strtrim = rtrim($string,","); //removed trailing comma from string
$violations = explode(",", $strtrim); // string to array conversion
foreach($violations as $violation) {
echo $violation;
$sql3 = "SELECT *
FROM user_infractions
INNER JOIN infraction_rules ON user_infractions.rules = infraction_rules.rule_id
WHERE user_infractions.rules = ?;";
$stmt3 = $conn->prepare($sql3);
//$stmt -> mysqli_stmt_prepare($stmt, $sql);
$stmt3->bind_param("s", $violation);
$stmt3->execute();
$result3 = $stmt3->get_result();
if ($result3->num_rows > 0) {
while ($row3 = $result3->fetch_assoc()) {
echo $row3['rule_long_desc'];
}
}
}
SOLUTION: Make sure you don't 'use up' any $responses->fetch_assoc()s before the while loop.
I performed mysqli_fetch_array($responses);.
In php I have this sql query (simplified for your convenience, but the problem remains)
$sql = "SELECT id, content FROM responses ORDER BY RAND()";
$responses = $conn->query($sql);
where the responses table looks like this:
+----+----------+--------+------+
| id | content | userId | part |
+----+----------+--------+------+
| 4 | peewee | 31 | 1 |
| 5 | tallinn | 31 | 1 |
| 6 | dewey | 31 | 1 |
| 7 | stanford | 31 | 1 |
+----+----------+--------+------+
That doesn't format properly so all you need to know is that the id and content rows are different for each entry while the rest is the same for each.
The problem is, when I do a while loop on $responses like so:
while ($row = $responses->fetch_assoc()) {
$responseId = $row["id"];
$content = $row["content"];
echo " id: ".$responseId;
echo " content: ".$content;
}
I always get 1 record fewer than there are. In this case, since there are 4 rows, I would only see 3 echoed. However, it is not always the same 3, nor are they in the same order. If I remove the ORDER BY RAND() clause, then it is always the first record which is left out.
Thanks in advance
Cheers
I have four columns in a properties table: property_id, value, id, material_id.
I also have an array of properties: Array $properties
The schema is a bit complicated, because I want to find the material_id based on the matching properties.
An example:
$properties = array(['property_id'=>1,'value'=>3],['property_id'=>2,'value'=>6],['property_id'=>3,'value'=>4]);
Example table output:
+----+-------------+-------------+-------+
| id | material_id | property_id | value |
+----+-------------+-------------+-------+
| 1 | 1 | 3 | 5 |
| 2 | 1 | 3 | 5 |
| 3 | 1 | 3 | 5 |
| 4 | 2 | 1 | 3 |
| 5 | 2 | 2 | 6 |
| 6 | 2 | 3 | 4 |
| 10 | 4 | 1 | 9 |
| 11 | 4 | 2 | 3 |
| 12 | 4 | 3 | 6 |
+----+-------------+-------------+-------+
Now, I need material_id that satisfies all the properties. How can I do that..? Do I need to use exist statement of MySQL?
Now, for each element in your array you will want to run a statement that looks like this:
SELECT material_id FROM properties WHERE property_id = 2 AND value = 3;
Do you need help on the php code also? You could run a for each loop, but I will need to know what way you are using to communicate with your database for more specifics.
edit
foreach ($properties as $foo => $bar)
{
$sql = 'SELECT material_id FROM properties WHERE ';
foreach ($bar as $key => $value)
{
$sql .= $key .' = '. $value .' AND ';
}
$sql .= 'true';
*run your PDO code on $sql here*
}
On behalf of performance, it's not a good idea to run a query per array's value. If you have an oversized array things can get pretty slower.
So, best solution can be to build a single query including all conditions presented on $properties array:
<?php
$properties = array(['property_id'=>1,'value'=>3],['property_id'=>2,'value'=>6],['property_id'=>3,'value'=>4]);
$qCondition = [];
foreach($properties as $prop) {
$q = sprintf("(property_id = %d AND value = %d)", $prop["property_id"], $prop["value"]);
$qCondition[] = $q;
}
// assuming that your database table name is 'materials'
$sql = sprintf("SELECT * FROM materials WHERE (" . implode(" OR ", $qCondition) . ")");
echo $sql;
Result:
SELECT * FROM materials
WHERE ((property_id = 1 AND value = 3) OR (property_id = 2 AND value = 6) OR (property_id = 3 AND value = 4))
Therefore, you need to run only one single query to get all desired rows.
You can play with suggested solution here: http://ideone.com/kaE4sw
I need to count how many times in ripeted the same values in different columns for the same id..
I'll try to clarify with an example:
TABLE:
+-----+-----+-----+-----+-----+
| id | d01 | d02 | d03 | d04 |
+=====+=====+=====+=====+=====+
| 1 | A | A | B | B |
+-----+-----+-----+-----+-----+
| 2 | A | A | A | A |
+-----+-----+-----+-----+-----+
| 3 | B | B | A | A |
+-----+-----+-----+-----+-----+
| 4 | A | A | A | A |
+-----+-----+-----+-----+-----+
| 5 | A | A | A | A |
+-----+-----+-----+-----+-----+
| 6 | B | A | A | A |
+-----+-----+-----+-----+-----+
I need to know how many times the value "B" is repeating for any person (ID)..
Is that possible to do that? RESULTS
+-----+-----+-----+
| id | count B |
+=====+=====+=====+
| 1 | 2 |
+-----+-----+-----+
| 2 | 0 |
+-----+-----+-----+
| 3 | 2 |
+-----+-----+-----+
I was thinking to use the function "SUM" but I have no idea how to display just the single ID.
Thanks in advance, hope the question is clear enough!
If there are only four columns:
SELECT id, (d01 = 'B') + (d02 = 'B') + (d03 = 'B') + (d04 = 'B')
FROM tablename
No there are 31 columns
That's a problem which you can solve in two ways:
Repeat the condition for the other 27 columns :)
Normalize your structure so that each value is dependent on both the id and a numeric value that represents a calendar.
The PHP way
You can also fetch all columns and let PHP solve this for you:
$res = $db->query('SELECT * FROM tablename');
foreach ($res->fetchAll(PDO::FETCH_ASSOC) as $row) {
$id = $row['id'];
unset($row['id']); // don't count the id column
$count = count(array_keys($row, 'B', true));
printf("ID %d: %d\n", $id, $count);
}
Since you seem to be using mysql_*:
// SHOW COLUMNS returns all the columns and constrains of the defined table
// We only need the column names so we will be later calling it by 'Field'
$sql = mysql_query("SHOW COLUMNS FROM table"); //your table name here
$val_to_count = 'B'; //value to count here
$id = 1; //id to search for
$new_sql = 'SELECT id, ';
// In this loop we will construct our SELECT query using the columns returned
// from the above query
while($row=mysql_fetch_array($sql)){
if($row['Field']!='id'){
$new_sql .= ' ('.$row['Field'].' = "'.$val_to_count.'") + ';
}
}
//Removing the last "+ " produced in the select query
$new_sql = rtrim($new_sql,"+ ");
$new_sql .= ' as count FROM table WHERE id = '.$id; //table name here again
// so $new_sql now has an output like:
// SELECT ID, (d01 = 'B') + (d02 = 'B') ... WHERE id = 1
$sql2 = mysql_query($new_sql);
//executing the constructed query with the output below
while($row2=mysql_fetch_array($sql2)){
echo 'ID - '.$row2['id']."<br>";
echo 'Count - '.$row2['count']."<br>";
}
Note:
mysql_* is deprecated, please consider to migrate to mysqli_*
I insert multiple id from my checkbox to MySQL database using php post form. In example I insert id (checkbox value table test) to mysql. Now I need a function to retrieve data from MySQL and print to my page with my example output (print horizontal list name of table test where data = userid)
My checkbox value (table name is test):
id | name
----+-------
1 | test1
2 | test2
3 | test3
4 | test4
5 | test5
6 | test6
7 | test7
9 | test9
MySQL data insert (name of table usertest):
id | data | userid
----+---------+--------
1 | 1:4:6:9 | 2
2 | 1:2:3:4 | 5
3 | 1:2 | 7
Example outout :( print horizontal list name of table test where data = userid )
user id 2 choise : test1 - test4 - test6 - test9
Thanks
Assuming your usertest table has only the three columns listed in your example you should replace it with the following -
CREATE TABLE usertest (
data INTEGER NOT NULL,
userid INTEGER NOT NULL,
PRIMARY KEY (data, userid)
);
Then your data will look like -
+------+--------+
| data | userid |
+------+--------+
| 1 | 2 |
| 4 | 2 |
| 6 | 2 |
| 9 | 2 |
| 1 | 5 |
| 2 | 5 |
| 3 | 5 |
| 4 | 5 |
| 1 | 7 |
| 2 | 7 |
+------+--------+
Querying this data then becomes trivial -
SELECT usertest.userid, GROUP_CONCAT(test.name SEPARATOR ' - ')
FROM usertest
INNER JOIN test
ON usertest.data = test.id
GROUP BY usertest.userid
You can read more about GROUP_CONCAT here
You could use a PHP solution and store the possible checkbox values in an array indexed by their ids. Something like -
<?php
$db = new PDO('mysql:dbname=test;host=127.0.0.1', 'user', 'pass');
$sql = 'SELECT id, name FROM test';
$stmt = $db->prepare($sql);
$stmt->execute();
$array = array();
while ($row = $stmt->fetchObject()) {
$array[$row->id] = $row->name;
}
$sql = 'SELECT userid, data FROM usertest';
$stmt = $db->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetchObject()) {
$data = explode(':', $row->data);
foreach($data as $key => $val) {
$data[$key] = $array[$val];
}
print "user id {$row->userid} choise : " . implode(' - ', $data) . "<br/>\n";
}