Order array items based on their occurrence desc in php - php

I have an array of mysql records in $allrecords variable.
There are multiple keys for each record and one of the key is called type.
Some of the variable has the same type.
E.g. it looks like this:
Seat
Mercedes
BMW
BMW
Mercedes
Audi
Mercedes
Fiat
Mercedes
Audi
Fiat
Mercedes
The array is unordered now (just grabbed from database) and now I need to order the array items from the most occurance one to the least.
E.g. like this
Mercedes (5)
Audi (3)
BMW (2)
Fiat (2)
Seat (1)
I do not need the numbers (that I get using another foreach loop), so I need it just like this:
Mercedes
Audi
BMW
Fiat
Seat
How to do such this in PHP? Is it possible? I need to group the items based on the type and then order them from the most to the least occurance.
Thanks in advance.
EDIT:
My array look like this:
Array
(
[0] => stdClass Object
(
[id] => 125
[user_id] => 29
[show] => 1
[state] => 1
[type] => 23
[subcat_id] => 11
[category_id] => 2
[name] => SLK 350
)
)

<?php
$groups = array();
foreach($allrecords as $record){
$type = $record->type;
if(empty($groups[$type]))
$groups[$type] = 1;
else
$groups[$type]++;
}
asort ($groups);
$cars = array_keys($groups);
print_r($cars);

usort($allrecords, function($a, $b){ return $a->count >= $b->count; });
where "count" is the name of the property...

var_dump(str_word_count(implode(" ", $all_records))); // Returns array( "Mercedes" => 5 ... )

aaaah i didn't get that!!!
you should use SQL to achieve this!!!
SELECT type, COUNT(1) FROM cars GROUP BY type;

Related

How to create a three dimensional array from sql query PHP

I have 2 tables in a database, 1 of them are linked with a foreign key to the first one. Each row on table 1 is linked to multiple rows in table 2. I am trying to make a query that looks at a WHERE from table 2 and returns multiple rows from table 2 which are sorted into the rows they linked with in table 1 and then put this all into one big multi dimensional array, so it should work something like this:
$array[0][column_name][0] this would use row 1 from table 1 and give me a the first result in the column called column_name
$array[1][column_name][0] this would use row 2 from table 1 and give me a the first result in the column called column_name
$array[1][column_name][3] this would use row 2 from table 1 and give me a the 4th result in the column called column_name
etc
How can I query this and store it in a 3 dimensional array using PHP.
I have tried to word this in as clear manner as possible, if you are unsure what I am asking, please comment and I will update my question to make it clearer.
Assume that we have two tables, Company and Employee:
Company
------------------
ID Company_Name
1 Walmart
2 Amazon.com
3 Apple
Employee
---------------------------------
ID Company_Id Employee_Name
1 1 Sam Walton
2 1 Rob Walton
3 1 Jim Walton
4 1 Alice Walton
5 2 Jeff Bezos
6 2 Brian T. Olsavsky
7 3 Steve Jobs
8 3 Tim Cook
The easiest way to envision a multi-dimensional (nested) array is to mimic the looping required to get it: outer loop is the company, inner loop is the employees:
// ignoring database access, this is just pseudo code
$outer = [];
// select id, company_name from company
foreach $companyResult as $companyRow {
// select * from employee where company_id = ? {$companyRow['id']}
$inner= [];
foreach $employee_result as $employeeRow {
$inner[] = $employeeRow; // ie, ['id'=>'1','Company_Id'=>'1','Employee_Name'=>'Sam Walton']
}
$outer[] = $inner;
}
print_r($outer);
// yields ====>
Array
(
[0] => Array
(
[0] => Array
(
[id] => 1
[Company_Id] => 1
[Employee_Name] => Sam Walton
)
[1] => Array
(
[id] => 2
[Company_Id] => 1
[Employee_Name] => Rob Walton
)
[2] => Array
(
[id] => 3
[Company_Id] => 1
[Employee_Name] => Jim Walton
)
[3] => Array
(
[id] => 4
[Company_Id] => 1
[Employee_Name] => Alice Walton
)
)
[1] => Array
(
[0] => Array
(
[id] => 5
[Company_Id] => 2
[Employee_Name] => Jeff Bezos
)
[1] => Array
(
[id] => 6
[Company_Id] => 2
[Employee_Name] => Brian T. Olsavsky
)
)
[2] => Array
(
[0] => Array
(
[id] => 7
[Company_Id] => 3
[Employee_Name] => Steve Jobs
)
[1] => Array
(
[id] => 8
[Company_Id] => 3
[Employee_Name] => Tim Cook
)
)
)
It is also possible to do if you use associative arrays. Consider the flat file that this query produces:
select company.id company_id, company.name company_name,
emp.id employee_id, emp.employee_name
from company
inner join employee on company.id = employee.company_id
-----
company_id company_name employee_id employee_name
1 Walmart 1 Sam Walton
1 Walmart 2 Rob Walton
1 Walmart 3 Jim Walton
1 Walmart 4 Alice Walton
2 Amazon.com 5 Jeff Bezos
2 Amazon.com 6 Brian T. Olsavsky
3 Apple 7 Steve Jobs
3 Apple 8 Tim Cook
Just use the primary IDs as the keys for your arrays:
$employeeList = [];
foreach($result as $row) {
$cid = $row['company_name'];
$eid = $row['employee_name'];
// avoid uninitialized variable
// $employeeList[$row['company_name']] = $employeeList[$row['company_name']] ?? [];
// easier to read version of above
$employeeList[$cid] = $employeeList[$cid] ?? [];
// assign it...
$employeeList[$cid][$eid] = $row;
}
Or, if you simply want each company row to hold an array of employee names,
$employeeList[$cid][] = $row['employee_name'];
The way that I've shown you is useful if you know the company_id and want to find the associated rows:
foreach($employeeList[2] as $amazon_guys) { ... }
But it's not at all useful if you're trying to group by employee, or some other field in the employee table. You'd have to organize the order of your indexes by your desired search order.
In the end, it's almost always better to simply do another query and let the database give you the specific results you want.

Break array down into unique arrays for database insert

I have an array like this:
Array
(
[year] => 1994, 1995, 1996, 1997
[make] => Ford
[model] => Mustang, Mustang Cobra, Mustang GT
[engine] => 302, 302 H/O, V6
)
I am wanting to insert unique rows into my database with all the possible solutions in the array.
For example:
id year make model engine
1 1994 Ford Mustang 302
2 1994 Ford Mustang Cobra 302
3 1994 Ford Mustang GT 302
4 1994 Ford Mustang 302 H/O
...and so on
I need to be able to break down that array to get all possible solutions into a unique row. Some columns may not have a value. For example, the array may only contain several Make's. I would like to insert all the unique possibilities into an array.
Array
(
[0] => 1994, Ford, Mustang, 302
[1] => and so on...
)
Here is simple way, without database part, but I hope you can do that yourself:
$arr = array
(
'year' => '1994, 1995, 1996, 1997',
'make' => 'Ford',
'model' =>'Mustang, Mustang Cobra, Mustang GT',
'engine' => '302, 302 H/O, V6'
);
$years = explode(',',$arr['year']);
$makes = explode(',',$arr['make']);
$models = explode(',',$arr['model']);
$engines = explode(',',$arr['engine']);
foreach($years as $year) {
foreach($makes as $make) {
foreach($models as $model) {
foreach($engines as $engine) {
echo 'INSERT INTO yourtable '.$year.', '.$make.', '.$model.', '.$engine."\n";
}
}
}
}
If you need "all unique possibilities" (combinations), the most direct approach is to iterate your information array nesting each item the other. And for each combination created from an iteration, create an array with the collected information and add to a final array. Eg:in kind of pseudo code
finalArray = new array()
foreach(year as y)
foreach(make as m)
foreach(model as mo)
foreach(engine as e)
newArray = new array(y,m,mo,e)
add newArray to finalArray
hope it heps you

Remove array keys to be left with just data

I have an array from a database, I just want to be left with the productnames without the array structure to be shown.
public function selectAll ()
{
$stmt = Database::get()->query('SELECT `productname` FROM retrofootball_products');
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
The output of this is
Array ( [0] => Array ( [productname] => Manchester City 1981 Centenary FA Cup Final Shirt ) [1] => Array ( [productname] => Manchester City 1999 Playoff Winning Shirt ) )
I want to be left with
Manchester City 1981 Centenary FA Cup Final Shirt, Manchester City 1999 Playoff Winning Shirt
If you want comma separated use implode
You may use implode :
implode(',', $smt->fetchAll(PDO::FECTH_ASSOC));

MySQL: fetch a row and multiple related rows - possible?

Let's say I have one table: "cars" with 3 fields: id, brand, cost.
There's a second table: "models" with 3 fields: id, brand, model_name.
Each "cars" row can have multiple related "models" rows.
Is it possible to do an sql-select whose output looks like this?
edit: I use PHP for the database querys
array(
[0] => array(
[id] => 1
[brand] => mercedes
[cost] => 1000
[models] => array(
[0] => array(
[id] => 1
[brand] => mercedes
[model_name] => slk
)
[1] => array(
[id] => 2
[brand] => mercedes
[model_name] => clk
)
[2] => array(
[id] => 3
[brand] => mercedes
[model_name] => whatever
)
)
)
)
You need to add a foreign key relation to the models table, say car_id. Then:
SELECT * FROM cars JOIN models ON car_id = models.id;
This will output something similar to what you are looking for.
Assuming you are using PHP, using the output:
$query= "SELECT * FROM cars JOIN models ON car_id = models.id";
$r= #mysqli_query($dbc, $query);
while ($row= mysqli_fetch_array($r, MYSQLI_ASSOC)) {
$carstuff['id']=$row[id];
$carstuff['brand']=$row[brand];
$carstuff['cost']=$row[cost];
$carstuff[$row['models']][]=$row['model_name'];
}
var_dump($carstuff);
Note, that the id, brand and cost are repeatedly overwritten, but that is okay because they are overwritten with the same information. I'm not too sure about the cleanliness of the code, but that is the basic idea.
Try this:
Query:
SELECT c.ID, c.brand,c.cost, GROUP_CONCAT(model_name SEPARATOR '","') as models
, GROUP_CONCAT(m.ID SEPARATOR ',') as MID
, GROUP_CONCAT(m.brand SEPARATOR '","') as mbrand
FROM cars c
LEFT OUTER JOIN model m
ON m.brand = c.brand
GROUP BY brand;
Output:
ID BRAND COST MODELS MID MBRAND
1 audi 1000 m11","m22 4,5 audi","audi
1 mercedes 1200 m1","m2","m3 1,2,3 mercedes","mercedes","mercedes
Now in your php code you can process the MODEL,MID and MBrand
(By using explode)
$modelArray = explode(" ,", $row["MODELS");
SQLFIDDLE

Sort array by value, then randomly within those values BUT group certain elements - or revise MySQL query to combine it all?

So, let's say I want to sort an array in this order:
1) sort by total_weight
2) sort within those weights randomly
3) if there's an item within the same weight that is similar in name, group those items
This would result in something like so:
name: Delta 1 - total_weight: 5
name: Delta 1b - total_weight: 5
name: Charlie 12 - total_weight: 5
name: Charlie 12b - total_weight: 5
name: Charlie 12c - total_weight: 5
name: Alpha 10 - total_weight: 4
name: Delta 2 - total_weight: 3
name: Delta 2b - total_weight: 3
name: Bravo 5 - total_weight: 3
The array prior to sorting looks like so:
Array
(
[463] => stdClass Object
(
[name] => Delta 1b
[total_weight] => 5
)
[463] => stdClass Object
(
[name] => Charlie 12
[total_weight] => 5
)
[340] => stdClass Object
(
[name] => Charlie 12b
[total_weight] => 5
)
[340] => stdClass Object
(
[name] => Charlie 12c
[total_weight] => 5
)
[342] => stdClass Object
(
[name] => Delta 1
[total_weight] => 5
)
[532] => stdClass Object
(
[name] => Alpha 10
[total_weight] => 4
)
[203] => stdClass Object
(
[name] => Bravo 5
[total_weight] => 3
)
[206] => stdClass Object
(
[name] => Delta 2
[total_weight] => 3
)
[208] => stdClass Object
(
[name] => Delta 2b
[total_weight] => 3
)
I know that to sort by weight, then by alphabetical I could use usort:
function _sort_by_total_weight($a, $b)
{
if ($a->total_weight == $b->total_weight) {
return strcmp($a->name, $b->name);
}
return ($a->total_weight > $b->total_weight) ? -1 : 1;
}
But, I want the results to not be alphabetical and feel random, yet group together some relevant tracks. I realize I could throw a row in the db for sort order or something, but with 10,000+ records, it's not easily implemented. Any thoughts on how to crack this nut?
EDIT: So, I reworked this on the db side (MySQL) so that the query is weighted and ordered before it hits php:
$this->db->select('tracks.id,
tracks.name AS name,
tracks.filename,
tracks.url_name,
tracks.file_path_high,
tracks.filesize,
tracks.categories,
tracks.duration,
tracks.folder,
links.tag_id,
SUM(links.weight) AS total_weight,
tag_data.tag_name');
$this->db->distinct();
$this->db->from('music AS tracks');
$this->db->where_in('links.tag_id', array('1', '2');
$this->db->join('linked_tags AS links', 'links.track_id = tracks.id', 'inner');
$this->db->join('tags AS tag_data', 'tag_data.id = links.tag_id', 'inner');
$this->db->group_by("name", "total_weight");
$this->db->order_by('total_weight DESC, RAND(123)');
$this->db->limit($total, $offset);
But, now I have some near-duplicate entries in the result. For the where_in, is there a way to state that I only want entries that have entries for both 1, and 2 and not have it return all entries where 1 matches OR 2 matches?
You could shuffle() your array results. Example from PHP.net:
<?php
$numbers = range(1, 20);
shuffle($numbers);
foreach ($numbers as $number) {
echo "$number ";
}
?>

Categories