Reputation: 317
I have entries and entrymeta table structure as. id
is the primary key and entry_id
in entrymeta is foreign key to id in entries table.
entries table:
id created_at
1 2017-04-03
2 2017-07-05
entrymeta table:
id entry_id(foreign key to id) meta_key meta_value
1 1 Name Smith
2 1 Address Saniply
3 1 Profession Student
4 2 Name John
5 2 Address Aviero
6 2 Profession Businessman
When I execute a query:
$query = 'SELECT entry_id, created_at, meta_key, meta_value FROM entries INNER JOIN entrymeta WHERE entries.id = entrymeta.entry_id';
$wpdb->get_results( $query );
I get the result like:
Array
(
[0] => stdClass Object
(
[entry_id] => 1
[created_at] => 2017-04-03
[meta_key] => Name
[meta_value] => Smith
)
[1] => stdClass Object
(
[entry_id] => 1
[created_at] => 2017-04-03
[meta_key] => Address
[meta_value] => Saniply
)
[2] => stdClass Object
(
[entry_id] => 1
[created_at] => 2017-04-03
[meta_key] => Profession
[meta_value] => Student
)
[3] => stdClass Object
(
[entry_id] => 2
[created_at] => 2017-07-05
[meta_key] => Name
[meta_value] => John
)
[4] => stdClass Object
(
[entry_id] => 2
[created_at] => 2017-07-05
[meta_key] => Address
[meta_value] => Aviero
)
[5] => stdClass Object
(
[entry_id] => 2
[created_at] => 2017-07-05
[meta_key] => Profession
[meta_value] => Businessman
)
)
How can I achieve something like this instead?
Array
(
[0] => stdClass Object
(
[entry_id] => 1
[created_at] => 2017-04-03
[Name] => Smith
[Address] => Saniply
[Profession] => Student
)
[1] => stdClass Object
(
[entry_id] => 2
[created_at] => 2017-07-05
[Name] => John
[Address] => Aviero
[Profession] => Businessman
)
)
I am using wordpress, if it has any other simpler methods to achieve this please let me know. Thanks!
Upvotes: 0
Views: 76
Reputation: 47991
I am writing your array of objects (resultset) as $array
. My method will assign temporary keys to merge the duplicate entry-id objects. Using isset()
means that no unnecessary values overwrites occur while iterating.
Code: (Demo)
$array=[
(object)['entry_id'=>1,'created_at'=>'2017-04-03','meta_key'=>'Name','meta_value'=>'Smith'],
(object)['entry_id'=>1,'created_at'=>'2017-04-03','meta_key'=>'Address','meta_value'=>'Saniply'],
(object)['entry_id'=>1,'created_at'=>'2017-04-03','meta_key'=>'Profession','meta_value'=>'Student'],
(object)['entry_id'=>2,'created_at'=>'2017-07-05','meta_key'=>'Name','meta_value'=>'John'],
(object)['entry_id'=>2,'created_at'=>'2017-07-05','meta_key'=>'Address','meta_value'=>'Aviero'],
(object)['entry_id'=>2,'created_at'=>'2017-07-05','meta_key'=>'Profession','meta_value'=>'Businessman']
];
foreach($array as $obj){ // iterate all objs
$id=$obj->entry_id; // cache for more readable code
if(!isset($result[$id])){ // first occurrence of entry_id
$result[$id]=new \stdClass(); // avoid Warning: Creating default object from empty value
$result[$id]->entry_id=$id; // store entry_id
$result[$id]->created_at=$obj->created_at; // store created_at
}
$result[$id]->{$obj->meta_key}=$obj->meta_value; // unconditionally store meta_key and meta_value
}
var_export(array_values($result)); // remove temporary indexes and display
Output:
array (
0 =>
stdClass::__set_state(array(
'entry_id' => 1,
'created_at' => '2017-04-03',
'Name' => 'Smith',
'Address' => 'Saniply',
'Profession' => 'Student',
)),
1 =>
stdClass::__set_state(array(
'entry_id' => 2,
'created_at' => '2017-07-05',
'Name' => 'John',
'Address' => 'Aviero',
'Profession' => 'Businessman',
)),
)
Upvotes: 1
Reputation: 1696
You have to join entrymeta once for every key you want to include in your result, which isn't very scalable.
SELECT
e.*,
m_name.meta_value Name,
m_addr.meta_value Address,
m_prof.meta_value Profession
FROM
entries e
JOIN entrymeta m_name ON m_name.entry_id = e.id
AND m_name.meta_key = 'Name'
JOIN entrymeta m_addr ON m_addr.entry_id = e.id
AND m_addr.meta_key = 'Address'
JOIN entrymeta m_prof ON m_prof.entry_id = e.id
AND m_prof.meta_key = 'Profession'
Upvotes: 1