this is my first time posting here, although I have gotten many great tips and techniques reading the posts here.
Here is my objective:
I have 2 somewhat similar tables to compare. For each row of each table, I am pulling the fields I want into into an array.
I basically want to echo out the values of any array from one table that has matching values in the other array.
Here is my code, maybe it will be easier to understand.
$sql = "SELECT * FROM $i_comp ORDER BY `manufacturer`";
$statement = $objDb->query($sql);
$c_skus = $statement->fetchAll(PDO::FETCH_ASSOC);
$sql = "SELECT `sku_one`,`sku_two`,`qty`,`manufacturer`";
$sql .= "FROM $i_gas ORDER BY `manufacturer`";
$statement = $objDb->query($sql);
$d_skus = $statement->fetchAll(PDO::FETCH_ASSOC);
foreach ( $c_skus as $c_sku ) {
// i want to see if any values of this array exist in the array created hy
// the foreach loop below (yes, repeat for each row)
$c = array($c_sku['sku'],$c_sku['sku_one'],$c_sku['sku_two'],$c_sku['sku_three']);
foreach ( $d_skus as $d_sku ) {
$d = array($d_sku['sku_one'],$d_sku['sku_two']);
$intersect = array_intersect($c, $d);
echo '<pre>', print_r($intersect), '</pre>';
}
}
Here are the results I receive for each iteration of the code:
Array
(
)
1
It should also be noted that I am not concerned with the Keys, just the Values. Eventually, those values will be works into an INSERT statement but for the time being I just need to get the right results.
Anyways, thanks for any and all help!
This is usually done in SQL
if you want whole row that has at least 1 matching SKU in another table:
$sql = "
SELECT c.* FROM $i_comp AS c
JOIN $i_gas AS d
ON d.sku_one in (c.sku, c.sku_one, c.sku_two, c.sku_three)
OR d.sku_two in (c.sku, c.sku_one, c.sku_two, c.sku_three)
ORDER BY c.`manufacturer`";
$statement = $objDb->query($sql);
$c_skus = $statement->fetchAll(PDO::FETCH_ASSOC);
// all rows that have at least 1 matching sku on another table
print_r($c_skus);
If you want only SKUs
$sql = "
SELECT d.sku_one FROM $i_comp AS c
JOIN $i_gas AS d
ON d.sku_one in (c.sku, c.sku_one, c.sku_two, c.sku_three)
UNION
SELECT d.sku_two FROM $i_comp AS c
JOIN $i_gas AS d
OR d.sku_two in (c.sku, c.sku_one, c.sku_two, c.sku_three)
";
$statement = $objDb->query($sql);
$c_skus = $statement->fetchAll(PDO::FETCH_ASSOC);
// all skus that have at least 1 matching sku on another table
print_r($c_skus);
In PHP intersect variant you need to build the arrays separately and then use array_intersect
$c = array();
foreach ( $c_skus as $c_sku ) {
$c[] = $c_sku['sku'];
$c[] = $c_sku['sku_one'];
$c[] = $c_sku['sku_two'];
$c[] = $c_sku['sku_three'];
}
$d = array();
foreach ( $d_skus as $d_sku ) {
$d[] = $d_sku['sku_one'];
$d[] = $d_sku['sku_two'];
}
$intersect = array_intersect($c, $d);
echo '<pre>', print_r($intersect), '</pre>';
Related
A form's checkboxes are stored as comma separated values in a single row as a string in mysql. I cannot control this.
When trying to get the top responses, both finding what the responses are, and how many times they appear, I run this:
$query = "SELECT `answer`, COUNT(*) AS CNT FROM `responses` WHERE `answer` <> '' GROUP BY `answer` ORDER BY CNT DESC ";
The individual comma separated values are not counted, rather the combination of them.
Example, 4 people submit checkboxes A and B. 2 only select A, 1 selects A and B, 1 selects B
The result of query above looks like:
A (2)
A,B (1)
B (1)
What I want to achieve is it separating the comma seperated values and yielding:
A (3)
B (2)
I have seen some php explode examples and tried as follows:
if ($result->num_rows > 0) {
while($rows = mysqli_fetch_assoc($result)) {
$ans=explode(',', $rows['answer']);
foreach($ans as $separated) {
echo "<div>".$separated."</div>";
}
}
The result looks like:
a
a
a
b
b
Now how do I store them to count, and then order from most selected to least?
Is my best route to use explode? Or is there another way that is simpler and more logical?
This link explains the issue, and they have a google side fix, but mysql doesn't have the commands: https://support.google.com/docs/thread/54705332?hl=en
Thanks!
###########################################
As answered below, the new code is:
$query = "SELECT `ans_4` FROM `responses` WHERE `ans_4` <> ''";
$result = $conn->query($query);
if ($result->num_rows > 0) {
$ans = [];
while($rows = mysqli_fetch_assoc($result)) {
$ans = array_merge($ans, explode(', ', $rows['answer']));
}
$count = array_count_values($ans);
arsort($count);
foreach ($count as $key => $value) {
echo "<div><span>$key</span><span>$value</span></div>";
}
For PDO:
$stmt = $pdo->query("SELECT ans_4 FROM responses WHERE ans_4 <> ''");
$ans = [];
while ($rows = $stmt->fetch(PDO::FETCH_ASSOC))
{
$ans = array_merge( $ans, explode( ', ', $rows[ 'ans_4' ] ) );
}
$count = array_count_values( $ans );
arsort( $count );
echo( "Largest Concerns" );
foreach ( $count as $key => $value ) {
echo "<div><span>$key</span><span>$value</span></div>";
}
Obviously this is not the best way to store them, and I'm not sure if you can do it in the query. But you probably want to just select that column:
SELECT `answer` FROM `responses` WHERE `answer` <> ''
Then explode and add to a flat array and count the values:
$ans = [];
while($rows = mysqli_fetch_assoc($result)) {
$ans = array_merge($ans, explode(',', $rows['answer']));
}
$count = array_count_values($ans);
The $count array should then yield something like:
Array
(
[A] => 3
[B] => 2
)
Then if needed to sort descending:
arsort($count);
Here this line $find_cond = str_replace('|',' ',$rem_exp); returns 225 and 245 number.
I want to get the records based on these two id number. But this below code returns the output repeatedly.
How do I properly put the while loop code inside a foreach?
foreach($arr_val as $key => $val)
{
$c_subsubtopic = str_replace('-','_',$subsubtopic);
$rem_exp = $val[$c_subsubtopic];
$find_cond = str_replace('|',' ',$rem_exp);
$sql = "SELECT a.item_id, a.item_name, a.item_url, b.value_url, b.value_name, b.value_id FROM ".TBL_CARSPEC_ITEMS." a, ".TBL_CARSPEC_VALUES." b WHERE a.item_id = b.item_id AND a.item_url = '".$subsubtopic."' AND value_id = '".$find_cond."' AND a.status = '1'";
while($r = mysql_fetch_array(mysql_query($sql)))
{
echo $r['value_name'];
}
}
The problem is that you are redoing the sql query at every iteration of the loop, thus resetting the results internal pointer, so you keep fetching the same array.
$res = mysql_query($sql)
should be on it's own line before the while loop, and then
while($r = msql_fetch_array($res))
This will properly increment through the $res list.
Try this and you are done
As you were getting may get multiple id in the string after replacing it so its better to use IN the where clause
foreach($arr_val as $key => $val)
{
$c_subsubtopic = str_replace('-','_',$subsubtopic);
$rem_exp = $val[$c_subsubtopic];
$find_cond = str_replace('|',',',$rem_exp);
$sql = "SELECT a.item_id, a.item_name, a.item_url, b.value_url, b.value_name, b.value_id FROM ".TBL_CARSPEC_ITEMS." a, ".TBL_CARSPEC_VALUES." b WHERE a.item_id = b.item_id AND a.item_url = '".$subsubtopic."' AND value_id IN('".$find_cond."') AND a.status = '1'";
while($r = mysql_fetch_array(mysql_query($sql)))
{
echo $r['value_name'];
}
}
I have this table in MySql db:
After running this query:
SELECT score, count(*) FROM Coaches group by score ORDER BY score DESC
The result table look like this:
Now in php I try to fetch the result and iterate through the array to determine which group each coach belongs to and get his place in the ranking. Therefore I wrote this:
$groupsOfScoresQuery = "SELECT score, count(*) FROM Coaches group by score ORDER BY score DESC";
$result = mysqli_query($dbc, $groupsOfScoresQuery);
if ($result) { // query did successfully run
$response['topCoaches'] = array();
if (mysqli_num_rows($result) > 0) {
while ( $rowScore = mysqli_fetch_array($result, MYSQLI_ASSOC) ) {
$currentRanking++;
$score = array(); // temp user array for one group of scores
$numberOfCoaches; // Number of coaches with this particular number of scores
$scoresGroup; // Scores in the particular group
$score["scores"] = $rowScore["score"];
$score["count"] = $rowScore["count(*)"];
$numberOfCoaches = $score["count"];
$scoresGroup = $score["scores"];
$response["scoresGroup"] = $scoresGroup; // HERE IS THE PROBLEM
.
.
.
more processing
} // end WHILE
Why $response["scoresGroup"] will always conatins the last value from the result? In this case this is 123. I thought that this is the first iteration through the loop and $response["scoresGroup"] wll hold first element (474), during the second iteration should hold 382 ? What I'm doing wrong here? Do I use correct function to fetch result? or should I use different loop to acheive my goal? Thanks for the help in advance.
You did not post the expected structure of $response; here is what I think you are trying to do:
while ($rowScore = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
$response["scoresGroup"][] = array(
"scores" => $rowScore["score"],
"count" => $rowScore["count(*)"]
);
}
// $response["scoresGroup"][0]["scores"] = 474
// $response["scoresGroup"][0]["count"] = 1
// $response["scoresGroup"][1]["scores"] = 382
// $response["scoresGroup"][1]["count"] = 1
// $response["scoresGroup"][2]["scores"] = 123
// $response["scoresGroup"][2]["count"] = 1
Or perhaps:
while ($rowScore = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
$response["scoresGroup"][$rowScore["score"]] = $rowScore["count(*)"]
}
// $response["scoresGroup"][474] = 1
// $response["scoresGroup"][382] = 1
// $response["scoresGroup"][123] = 1
if (mysqli_num_rows($result) > 0) {
while ( $rowScore = mysqli_fetch_array($result, MYSQLI_ASSOC) ) {
$currentRanking++;
$score = array(); // temp user array for one group of scores
$numberOfCoaches; // Number of coaches with this particular number of scores
$scoresGroup; // Scores in the particular group
$score[]["scores"] = $rowScore["score"];
$score[]["count"] = $rowScore["count(*)"];
$numberOfCoaches[] = $score["count"];
$scoresGroup[] = $score["scores"];
$response[]["scoresGroup"] = $scoresGroup; // HERE IS THE PROBLEM
Looking at the description of your question, you need to define a multidimensional array for storing all the results from query resultset.
Please refer the below code snippet
$groupsOfScoresQuery = "SELECT score, count(*) FROM Coaches group by score ORDER BY score DESC";
$result = mysqli_query($dbc, $groupsOfScoresQuery);
if ($result) { // query did successfully run
$response['topCoaches'] = array();
if (mysqli_num_rows($result) > 0) {
while ( $rowScore = mysqli_fetch_array($result, MYSQLI_ASSOC) ) {
$currentRanking++;
$score = array(); // temp user array for one group of scores
$numberOfCoaches; // Number of coaches with this particular number of scores
$scoresGroup; // Scores in the particular group
$score["scores"] = $rowScore["score"];
$score["count"] = $rowScore["count(*)"];
$numberOfCoaches = $score["count"];
$scoresGroup = $score["scores"];
$response["scoresGroup"][] = $scoresGroup; //Notice the array here
.
.
.
more processing
} // end WHILE
You are settings $response['scoresGroup'] each time you run the loop, so at the end, it will contain only the last element. Try changing the variable you put the data into on each loop.
$x++;
$response['scoresGroup' . x] = $scoresGroup;
I am wanting to order my array by how many times a value comes up in that array and also then print only the highest 6 results.
This is what I have at the moment:
$delimiter = " ";
$tags = array();
$sql = mysql_query("SELECT tags FROM share WHERE site_id = $id");
while($result = mysql_fetch_assoc($sql)) {
$tags_new = explode($delimiter, $result['tags']);
$tags = array_merge($tags , $tags_new);
}
Hum... You can do that:
while($result = mysql_fetch_assoc($sql)) {
$tags_new = explode($delimiter, $result['tags']);
foreach($tags_new as $tag){
$tags[$tag]++;
}
}
After, you need to sort by value, using function sort or rsort (desc).
rsort($tags);
Last, you need slice and get only 6 first:
$high_tags = array_slice($tags, 0, 6, true);
Edit: showing key and value:
foreach($high_tags as $key => $value){
echo "{$key}: {$value}";
}
Or just do:
$high_keys = array_keys($high_tags);
var_dump($high_keys);
Bye :)
You can do this in MySQL with the following query:
SELECT tags, COUNT(tags) AS tag_count
FROM share WHERE site_id = $id
GROUP BY tags
ORDER BY tag_count DESC
LIMIT 6;
This will select the top 6 tags with the highest count. You can then loop over them similar to the PHP code you already have.
I'm trying to mesh the below mysql query results into a single json object, but not quite sure how to do it properly.
$id = $_POST['id'];
$sql = "SELECT contracts.po_number, contracts.start_date, contracts.end_date, contracts.description, contracts.taa_required, contracts.account_overdue, jobs.id AS jobs_id, jobs.job_number, companies.id AS companies_id, companies.name AS companies_name
FROM contracts
LEFT JOIN jobs ON contracts.job_id = jobs.id
LEFT JOIN companies ON contracts.company_id = companies.id
WHERE contracts.id = '$id'
ORDER BY contracts.end_date";
$sql2 = "SELECT types_id
FROM contracts_types
WHERE contracts_id = '$id'";
//return data
$sql_result = mysql_query($sql,$connection) or die ("Fail.");
$arr = array();
while($obj = mysql_fetch_object($sql_result)) { $arr[] = $obj; }
echo json_encode($arr); //return json
//plus the selected options
$sql_result2 = mysql_query($sql2,$connection) or die ("Fail.");
$arr2 = array();
while($obj2 = mysql_fetch_object($sql_result2)) { $arr2[] = $obj2; }
echo json_encode($arr2); //return json
Here's the current result:
[{"po_number":"test","start_date":"1261116000","end_date":"1262239200","description":"test","taa_required":"0","account_overdue":"1","jobs_id":null,"job_number":null,"companies_id":"4","companies_name":"Primacore Inc."}][{"types_id":"37"},{"types_id":"4"}]
Notice how the last section [{"types_id":"37"},{"types_id":"4"}] is placed into a separate chunk under root. I'm wanting it to be nested inside the first branch under a name like, "types".
I think my question has more to do with Php array manipulation, but I'm not the best with that.
Thank you for any guidance.
Combine the results into another structure before outputting as JSON. Use array_values to convert the type IDs into an array of type IDs. Also, fix that SQL injection vulnerability. Using PDO, and assuming the error mode is set to PDO::ERRMODE_EXCEPTION:
$id = $_POST['id'];
try {
$contractQuery = $db->prepare("SELECT contracts.po_number, contracts.start_date, contracts.end_date, contracts.description, contracts.taa_required, contracts.account_overdue, jobs.id AS jobs_id, jobs.job_number, companies.id AS companies_id, companies.name AS companies_name
FROM contracts
LEFT JOIN jobs ON contracts.job_id = jobs.id
LEFT JOIN companies ON contracts.company_id = companies.id
WHERE contracts.id = ?
ORDER BY contracts.end_date");
$typesQuery = $db->prepare("SELECT types_id
FROM contracts_types
WHERE contracts_id = ?");
$contractQuery->execute(array($id));
$typesQuery->execute(array($id));
$result = array();
$result['contracts'] = $contractQuery->fetchAll(PDO::FETCH_ASSOC);
$result['types'] = array_values($typesQuery->fetchAll(PDO::FETCH_NUM));
echo json_encode($result); //return json
} catch (PDOException $exc) {
...
}
If $contractQuery returns at most one row, change the fetch lines to:
$result = $contractQuery->fetch(PDO::FETCH_ASSOC);
$result['types'] = array_values($typesQuery->fetchAll(PDO::FETCH_NUM));
It would seem like you'd be better served by consolidating the two queries with a JOIN at the SQL level. However, assuming the two arrays have equal length:
for ($x = 0, $c = count($arr); $x < $c; $x++) {
if (isset($arr2[$x])) {
$arr[$x] += $arr2[$x];
}
}
echo json_encode($arr);
Edit: you would need to change from mysql_fetch_object to mysql_fetch_assoc for this to work properly.
Why are you using 2 distinct arrays ? I would simply add the rows of the 2nd query in $arr instead of $arr2. This way, you end up with a single array containing all rows from the 2 queries.