How to do SQL's GROUP BY using PHP? - php

I'd like to SELECT rows from a database table and group them using PHP instead of SQL based on a parameter (in this case by item).
SQL:
Clothes table
id item owner
1 shoes joe
2 pants joe
3 hat joe
4 pants joe
5 hat tom
SELECT * from Clothes where owner='joe'
1 shoes joe
2 pants joe
3 hat joe
4 pants joe
Here's how I'd like the results to look after using PHP instead of SQL's GROUP BY item
PHP :
1 shoes joe
2 pants joe //count 2
3 hat joe
I'm sure there is a PHP array function for this I'm just not familiar, thoughts?

The easiest way is to exploit the uniqueness of array keys:
$grouped = array();
while ($row = $db->fetchResult()) { // or however you get your data
if (isset($grouped[$row['item']])) {
$grouped[$row['item']]['count']++;
} else {
$grouped[$row['item']] = $row + array('count' => 1);
}
}

Using pseucode for the database access functions, I believe this should work:
$sql = "SELECT * from Clothes where owner='joe'";
$res = query($sql);
$arr = array();
while ($row = $res->fetch())
{
$arr[] = $row['item'];
}
$arr = array_unique($arr);
You should note that this might give you a "sparse array" (in other words, there may be gaps in the keys). And as said in the comments, it's usually better to do this in SQL if you have that option. Even if that means executing two similar queries.

function group($items, $field) {
$return = array();
foreach ($items as $item) {
$key = $item[$field];
if (isset($return[$key])) {
$return[$key]['count']++;
} else {
$return[$key] = $item;
$return[$key]['count'] = 1;
}
}
return $return;
}
print_r(group($results, "item"));

Related

Trying to sort and display data from a single mysql query

I've looked for about an hour. I may even be looking for the wrong thing, because I'm sure this is a common practice. In the past, I would have just ran mutliple querys or had something hard coded, but I'm trying to do things the most efficient way.
I have a query that brings back this data:
factoryId | serviceID | serviceName
1 1001 repair
1 1002 recycle
1 1003 transfer
2 1001 repair
2 1002 recycle
2 1003 transfer
3 1001 repair
3 1002 recycle
3 1003 transfer
I need to put it into sections with headers...
// switch statement determines factory name from id ?>
Factory One
Repair
Recycle
Transfer
Factory Two
Repair
Recycle
Transfer
Factory Three
Repair
Recycle
Transfer
I think the solution is with multi-dimensional arrays, but not sure how to write the array, and then (2 foreach loops?) to echo the formatted result.
Here this is what you can do, I am not using the query but generated an array which is similar to mysql_fetch_assoc();
<?php
$array[] = array("factory"=>"Factory One","serviceName"=>"repair");
$array[] = array("factory"=>"Factory One","serviceName"=>"recycle");
$array[] = array("factory"=>"Factory One","serviceName"=>"transfer");
$array[] = array("factory"=>"Factory Two","serviceName"=>"repair");
$array[] = array("factory"=>"Factory Two","serviceName"=>"recycle");
$array[] = array("factory"=>"Factory Two","serviceName"=>"transfer");
$array[] = array("factory"=>"Factory three","serviceName"=>"repair");
$array[] = array("factory"=>"Factory three","serviceName"=>"recycle");
$array[] = array("factory"=>"Factory three","serviceName"=>"transfer");
$group_array = array();
foreach($array as $key=>$val){
$group_array[$val["factory"]][] = $val["serviceName"];
}
foreach($group_array as $key=>$val){
echo '<b>'.$key.'</b><br />';
foreach($val as $k=>$v){
echo '-'.$v.'<br />';
}
}
?>
The first loop is similar to looping the query result and creating a group array and then finally loop the group array to display the data.
Try the below code. Make sure to write your query appending ASC or DESC to factoryID
<?php
//Place a counter for factoryId
$countid_fid = 1;
$reset = 0; //this decides if the title should be printed or not. 1 means dont print.
//loop
while($row = mysql_fetch_object($q)) {
$fid = $row->factoryID;
if($countid_fid == $fid) {
if($reset = 0) {
echo $row->serviceName; //title
$reset = 1;
}
}else{
$reset = 0;
}
//rest of your code to show data
}
?>
Hope this help
SELECT * FROM factory GROUP BY factoryId;

drupal 6 php array of arrays not working

I'm trying to put values into name arrays from a table and array entries are over-riding each other
Code:
$list = array();
$name = db_query("SELECT name FROM {name_list}");
while ($num = db_fetch_array($name)){
$list[$num['name']]=array('title'=>$num['name']);
}
$values = db_query("SELECT id,name1,name2 FROM {status}");
while ($val = db_fetch_array($values)){
$list[$val['name1']] = array($val['id'] =>$val['id']);
$list[$val['name2']] = array($val['id'] =>$val['id']);
}
$output .= dprint_r($list);
The first while loop writes the titles of each array which are the names from the name db table.
The table:
name
Alice
Kate
Jason
John
Sam
the second while loop goes into the status table which looks something like:
id name1 name2
1 Alice Kate
2 Jason Kate
3 Kate Alice
4 Jason John
The final arrays should look something like:
Alice array (
1,3);
Jason array (
2,4);
Kate array (
1,2,3);
Sam array (
); etc...
Instead its looking like alice (3) Jason(4) Kate(3) etc...
Although I have no drupal for testing the error seems clear. Use the [] operator to push elements to the end of the id-per-name array. Try :
$list = array();
$name = db_query("SELECT name FROM {name_list}");
while ($num = db_fetch_array($name)){
$list[$num['name']]=array(); // initialize as empty array. you won't need the name
// twice as its already the index to $list
}
$values = db_query("SELECT id,name1,name2 FROM {status}");
while ($val = db_fetch_array($values)){
$list[$val['name1']][] = $val['id']; // add id to the first name's list
$list[$val['name2']][] = $val['id']; // add id to the second name's list
}

Count unique value from associative array

First, thanks for any help.
I've spent countless hours on here and other forums trying to find my exact solution but either 1) I'm not understanding the one's I've read or 2)I haven't found the right answer.
In PHP, I've run a somewhat complex query which returns a set of records similar to:
id | name | direction|
1 aaa east
2 bbb west
3 ccc east
I've created an associative array such as:
$query=("select * from foo");
$result=mysql_query($query);
$array=mysql_fetch_assoc($result);
Now, what I need to do seems simple but I'm not grasping the concept for some reason.
I need to loop through the entire $array and return a count of any value that I want to specify and store that count in a variable.
i.e. Show me how many times east shows up in the "direction" column and put that in a variable called $eastcount.
I've tried various combinations of using foreach loops with incremental counts and have tried using array_count_values but have not been able to put the pieces together :/
// build query
$query=("select * from foo");
// execute query
$result=mysql_query($query);
// declare vars
$east_count = 0;
// iterate through results
while ($data = mysql_fetch_array($result)) {
// grab DIRECTION column value
$direction = $data['direction'];
// detect 'east'
if ($direction == 'east') {
// increment 'east' count
$east_count++;
}
}
// print # of times we had 'east'
echo("direction said 'east' $east_count times");
This should work (sorry for the lack of code block I'm on my iPhone).
http://www.php.net/manual/en/function.array-count-values.php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
Array
(
[1] => 2
[hello] => 2
[world] => 1
)
How about this:
query=("select * from foo");
$result=mysql_query($query);
$directions = array();
while($direction = mysql_fetch_assoc($result) {
$directions[] = $direction['direction'];
}
$directionCounts = array_count_values($directions);
//now you can access your counts like this:
echo $directionCounts['east'];
First, of all you should be using mysqli instead. But, anyhow I hope this makes some sense.
if ($result) {
$count = 0;
while ( $row = mysql_fetch_assoc($result)) {
if ($row["route"] === "east") {
$count += 1;
}
}
return $count;
}

Break a special character in MySQL

I have a requirement where I need to check a pipe | in the database. If found I need to play around differently.
Here how my db table looks like //Please check the | character in row 11
And if I run a group by sql command myresult will be
Which is correct.
But my requirement is to break the | in any cell and give the count accordingly. The expected result as
Can this be done using MySQL commands alone or do I need to use some php script as well?
Any snippet will be helpful.
Hope this script might help u
$frt =array();
$stmt = $mysqli->prepare("select `fruits` from `meva`") or $mysqli->error ;
$stmt->execute();
$stmt->bind_result($fruits);
while ($stmt->fetch()) {
$frt[]=$fruits;
}
// var_dump($frt); //check all the fruits is in array
$res = array();
$tot = count($frt);
for($i=0;$i<=$tot;$i++)
{
if(preg_match("/\|/", $frt[$i]))
{
$res[] =explode( '|', $frt[$i]);
}else
{
$res[] = $frt[$i];
}
}
// var_dump($res);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($res));
foreach($it as $v) {
$ary[]=$v;
}
$all_fruits = array();
$tot_ary = count($ary);
for($io=0;$io<=$tot_ary;$io++)
{
if(isset($ary[$io])!='')
{
$all_fruits[] = trim($ary[$io]);
}else
{
continue;
}
}
// var_dump($all_fruits);
$newArray = array_count_values($all_fruits);
foreach ($newArray as $key => $value) {
echo "$key - <strong>$value</strong> <br />";
}
I think you should fix your data. You can run these two statements in a row until all the data is fixed:
INSERT INTO meva (fruits)
SELECT SUBSTR(fruits, LOCATE('|', fruits) - 1) FROM meva
WHERE LOCATE('|', fruits) > 0;
UPDATE meva
SET fruits = SUBSTR(fruits, LOCATE('|', fruits) + 1)
WHERE LOCATE('|', fruits) > 0;
This will fix the table.
However, if it is your interview question (or a school assignment) just to count from the table as it is, then you can only do it if you know the maximum number of pipes in a given row.
So, if the maximum number of pipes in a row is 1, then your select statement would be:
SELECT count(*),
CASE WHEN LOCATE('|', fruits) > 0 THEN SUBSTR(fruits, LOCATE('|', fruits) - 1) ELSE fruits END
FROM meva
GROUP BY CASE WHEN LOCATE('|', fruits) > 0 THEN SUBSTR(fruits, LOCATE('|', fruits) - 1) ELSE fruits END
If you can have more than one pipe in a row, then your CASE statement will be more complex
Actually the best solution is to change your data structure. This current structure is not recommended. each 'cell' has to contain only one value. If you need to store several fuirts for a specific ID, use
id fruit
11 Apple
11 Mango
this might require some adjustments to your code / tables, but it will prevent the need for more future hacks.
You can use php and do it like below
$query = mysql_query("SELECT fruit FROM meva");
$cnt_array = array();
while($row = mysql_fetch_assoc($query)){
$fruits = $row["fruit"];
$fruit = explode("|", $fruits);
foreach($fruit as $fru){
if(array_key_exists($fru,$cnt_array)){
$cnt_array[$fru] = $cnt_array[$fru]+1;
}
else{
$cnt_array[$fru] = 1;
}
}
}
print_r($cnt_array);
NOTE : This code is not tested,please try it and edit accordingly

SQL join results into an object in codeigniter

ok, a bit of background,
just into codeigniter
not a fan of sql and server-side scripts
i know what joins are
i have a many-to-many database for the first time
it's because joins typically have the following example as a result. but i wanted to parse this without having to build code to ignore repetitions. it's a 3-table join sample. the issue of repeating values increases as i join more tables:
table1.authorid table1.authorname table2.books table3.favorited
1 john john's book 1 jean
1 john john's book 1 joe
1 john john's book 2 ken
1 john john's book 2 mark
2 mark mark's book 1 alice
2 mark mark's book 1 ted
2 mark mark's book 2 sarah
2 mark mark's book 2 denise
is there a way in codeigniter (or plain PHP) that i can get this array form and turn it into something like json (and parse it like json)
$result = [
{
'authorid':1,
'authorname':'john',
'books':['john's book1','john's book2'],
'favorited':['jean','joe','ken','mark']
},
{
'authorid':2,
'authorname':'mark',
'books':['mark's book1','mark's book2'],
'favorited':['alice','ted','sarah','denise']
}
]
Update: this is not limited to this depth of objects/arrays (like in the example). it can go deeper (arrays in arrays, arrays in objects, objects in arrays, objects in objects)
// first, we need the SQL results in the $result_array variable
$sql = 'SELECT ...'; // your SQL command
$result_array = $this->db->query($sql)->result_array(); // codeigniter code
// here the real answer begins
$result = array();
foreach ($result_array as $row)
{
if (!isset($result[$row['authorid']])
{
$author = new StdClass();
$author->authorid = $row['authorid'];
$author->authorname = $row['authorname'];
$author->books = array($row['books']);
$author->favorited = array($row['favorited']);
$result[$row['authorid']] = $author;
}
else
{
if (!in_array($row['books'], $result[$row['authorid']]->books))
{
$result[$row['authorid']]->books[] = $row['books'];
}
if (!in_array($row['favorited'], $result[$row['authorid']]->favorited))
{
$result[$row['authorid']]->favorited[] = $row['favorited'];
}
}
}
$result = array_values($result);
echo json_encode($result);

Categories