mysql select all, group by orderid - php

I was wondering if anyone could help me with selecting information from my table, but grouping the results depending on the order id. I'm sure this is quite simple, but I can't seem to get the code working.
Here's my attempt - which is only showing 1 result, instead of 6:
4 results with orderid 55542
2 results with orderid 55543
SQL:
SELECT *
FROM #__users_orders
WHERE userid = 22
GROUP BY orderid
ORDER BY date DESC
Any help would be appreciated :)
EDIT:
I'd like to acheive this (or something similar)
Array[55542]
(
[0] => stdClass Object
(
[id] => 6
[userid] => 66
[orderid] => 55542
[date] => 2011-08-05 16:30:24
[code] => 121021
[title] => 7 STAR CHICKEN A/KING 71198 1.3KG
[units] => 2
[ctns] =>
)
[1] => stdClass Object
(
[id] => 1
[userid] => 66
[orderid] => 55542
[date] => 2011-08-05 16:06:12
[code] => 302371
[title] => ANCHOVY FILL 730GM
[units] => 2
[ctns] =>
)
[2] => stdClass Object
(
[id] => 6
[userid] => 66
[orderid] => 55542
[date] => 2011-08-05 16:30:24
[code] => 121021
[title] => 7 STAR CHICKEN A/KING 71198 1.3KG
[units] => 2
[ctns] =>
)
[3] => stdClass Object
(
[id] => 1
[userid] => 66
[orderid] => 55542
[date] => 2011-08-05 16:06:12
[code] => 302371
[title] => ANCHOVY FILL 730GM
[units] => 2
[ctns] =>
)
)
Array[55543]
(
[0] => stdClass Object
(
[id] => 6
[userid] => 66
[orderid] => 55543
[date] => 2011-08-05 16:30:24
[code] => 121021
[title] => 7 STAR CHICKEN A/KING 71198 1.3KG
[units] => 2
[ctns] =>
)
[1] => stdClass Object
(
[id] => 1
[userid] => 66
[orderid] => 55543
[date] => 2011-08-05 16:06:12
[code] => 302371
[title] => ANCHOVY FILL 730GM
[units] => 2
[ctns] =>
)
)

SELECT *
FROM #__users_orders
WHERE userid = 22
ORDER BY orderid DESC
Just select your items like this and create your object/array hierarchy in the frontend by iterating over the results and creating a new array for every new orderid that comes by.

SELECT orderid, COUNT(*)
FROM #__users_orders
WHERE userid = 22
GROUP BY orderid
ORDER BY date DESC
Normally, you have to use an aggregate (eg COUNT, SUM) and GROUP BY matched. So that columns in the SELECT but not in the COUNT or SUM are in the GROUP BY
Only MySQL allows you to not follow this rule. Other DB engines would give an error.

the query seems ok, maybe your extracting the results the wrong way
SELECT * FROM table GROUP BY field1;
should return same number of rows than
SELECT field1, field2 FROM table GROUP BY field1;
but different number than
SELECT * FROM table;

You should not select "*" in this query.
When you group by "some columns". You can only select "some columns" or some_aggregate_function(other columns).
e.g. If you want to get the aggregate ordersize and latest date for each order id, you would do something like -
SELECT orderid, sum(ordersize), max(date) FROM #__users_orders WHERE userid = 22 GROUP BY orderid ORDER BY max(date) DESC

Related

Is there any possibility to assign an alias to all columns of a table at once?

As mentioned above, I am trying to assign an alias to all columns of a table at once as there is an obvious problem in PDO if a column name is used in more than one table.
If I'm trying this SQL statement:
SELECT t12.*,t1.*,t2.* FROM `tableone2tabletwo` t12
LEFT JOIN tableone t1 ON t12.idone=t1.id
LEFT JOIN tabletwo t2 ON t12.idtwo=t2.id
I'll receive an array like this with$stmt->fetch():
Array
(
[id] => 2
[0] => 1
[idone] => 1
[1] => 1
[idtwo] => 2
[2] => 2
[3] => 1
[name] => Test2TwoText
[4] => Test1Text
[5] => 2
[6] => Test2TwoText
)
As you see, the field gets overwritten(the last time by the last element with this name... ;-)), even though the table has an alias.
fetch(PDO::FETCH_ASSOC) as Andrii Filenko recommended returns this:
Array
(
[id] => 2
[idone] => 1
[idtwo] => 2
[name] => Test2TwoText
)
So here the data is even lost, not only just available via the numeric indices.
fetch(PDO::FETCH_NAMED) as Nigel Ren recommended returns this:
Array
(
[id] => Array
(
[0] => 1
[1] => 1
[2] => 2
)
[idone] => 1
[idtwo] => 2
[name] => Array
(
[0] => Test1Text
[1] => Test2TwoText
)
)
Is there a simple and stylish solution for this problem or will I have to do this one by one?
(My DB is available at DB-fiddle if you want to take a look!)

How laravel relationship internally works?

I have really surprised about laravel relationship becasue it gives result without duplicate entries while if compare to left join.
for example recently i tried self join has many to same table
public function parentMenu(){
return $this->hasMany(Page::class,'parent_page_id','id');
}
and it return following result
Array
(
[0] => Array
(
[id] => 1
[page_name] => Branch Details
[page_url] => #
[parent_page_id] => 0
[page_type] => 1
[created_at] => 2018-06-23 23:45:34
[updated_at] => 2018-06-23 23:45:34
[deleted_at] =>
[slug] => branch_detail
[parent_menu] => Array
(
[0] => Array
(
[id] => 2
[page_name] => Add Branch Detail
[page_url] => add-branch
[parent_page_id] => 1
[page_type] => 1
[created_at] => 2018-06-23 23:45:54
[updated_at] => 2018-06-23 23:45:54
[deleted_at] =>
[slug] => add_branch_detail
)
[1] => Array
(
[id] => 11
[page_name] => View Branch Detail
[page_url] => list-branch
[parent_page_id] => 1
[page_type] => 1
[created_at] => 2018-06-23 23:46:08
[updated_at] => 2018-06-23 23:46:08
[deleted_at] =>
[slug] =>
)
)
)
also i have tried to figure out the query
Array
(
[0] => Array
(
[query] => select * from `pages` where `pages`.`deleted_at` is null
[bindings] => Array
(
)
[time] => 0.82
)
[1] => Array
(
[query] => select * from `pages` where `pages`.`parent_page_id` in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) and `pages`.`deleted_at` is null
[bindings] => Array
(
[0] => 1
[1] => 2
[2] => 4
[3] => 5
[4] => 7
[5] => 8
[6] => 9
[7] => 10
[8] => 11
[9] => 12
)
[time] => 0.86
)
)
Now my question is suppose if i try to get same result what will be the mysql query .Since i want to know how internally relation query works ? will it do forloop internally or else in query itself it will produce result .
Also will it execute separate query in loop to retrieve child menu list ?
Laravel's active record implementation doesn't use joins for its relationships (well is does for some of them but that's for relationships like belongsToMany where it needs to use a pivot/intermediate table).
What will actually happen is Eloquent will get the related keys from the table and perform another query to get the required relationship e.g.
Post has many Comment and there are 3 posts in the db with ids 1, 2 and 3.
Post::with('comments')->get();
Will result in:
Query 1
SELECT * from `posts`
Query 2
SELECT * FROM `comments` WHERE `comment`.`post_id` in ('1', '2', '3')
It will hen go through the results from the 2nd query and match them to the models loaded from the first.
If you want to see what queries are being run from your Laravel app then I would suggest installing either:
Laravel Debugbar
Clockwork
Amongst other things, either of these tools will show you the queries that are being run.

How to group records from a database in a PHP foreach loop, then combine the values in to a new array?

I have a table in a MySQL database that is used to store games that someone can book on. The games can be held in more than one location but they can also share the same time as another game. Here is an example of the data in the array that is taken from the MySQL database:
[0] => Array
(
[id] => 174
[gamedatetime] => DateTime Object
(
[date] => 2016-02-08 14:00:00.000000
[timezone_type] => 3
[timezone] => Europe/London
)
[available] => 1
[gameID] => 1
[isBooked] =>
)
[1] => Array
(
[id] => 175
[gamedatetime] => DateTime Object
(
[date] => 2016-02-08 14:00:00.000000
[timezone_type] => 3
[timezone] => Europe/London
)
[available] => 1
[gameID] => 1
[isBooked] => 1
)
[2] => Array
(
[id] => 176
[gamedatetime] => DateTime Object
(
[date] => 2016-02-08 15:00:00.000000
[timezone_type] => 3
[timezone] => Europe/London
)
[available] => 1
[gameID] => 1
[isBooked] =>
)
What I need to do is create an array with this data on it, but grouped by the date and time, and the gameID are joined together but comma separated, like this:
[0] => Array
(
[gamedatetime] => 2016-02-08 14:00:00.000000
[id] => 174,175
)
[1] => Array
(
[gamedatetime] => 2016-02-08 15:00:00.000000
[id] => 176
)
How can I achieve this using PHP?
The following will achieve what you are aiming for but the ids will be in a subarray, allowing you to concatenate together as you need them.
$newArray = [];
foreach ($oldArray as $game) {
$newArray[$game['gamedatetime']]['gamedatetime'] = $game['gamedatetime'];
$newArray[$game['gamedatetime']]['ids'][] = $game['id'];
}
or you can change the query to something like:
SELECT gamedatetime, GROUP_CONCAT(id) as `id`
FROM game
WHERE ...
GROUP BY gamedatetime
You would be more efficient by using the mysql GROUP BY word that would immediately return the array you want.
If you just want to do it in php it's simply a matter of concatenate the results as you want them displayed which is not 100% clear to me in your question.
Try group_concat in query.
select gamedatetime, group_concat(`id` separator ',') as `id` from table group by gamedatetime;

code igniter form_dropdown() order

I am trying to order the dropdown items in alphabetical order but am unable to do so. I must be missing something obvious..
I assumed ORDER BY type_name would have created the array in alphabetical order
$data['training_types'] = $this->db->query("SELECT * FROM training_types ORDER BY type_name")->result_array();
print_r($training_types);
foreach ($training_types as $type)
{
$options[$type['id']] = $type['type_name'];
echo $options[$type['id']]; //test only: this displays the options in alphabetical order just fine
}
print_r($options);
echo form_dropdown('training_type',$options,'0');
//for some reason when the dropdown is created, the order is not alphabetical, it's not even ordered by id... I have no idea what is ordering it this way.
1st print_r returns:
Array ( [0] => Array ( [id] => 6 [type_name] => Independent Study ) [1] => Array ( [id] => 1 [type_name] => Instructor Lead ) [2] => Array ( [id] => 3 [type_name] => Instructor Lead/Virtual ) [3] => Array ( [id] => 7 [type_name] => Job Aid ) [4] => Array ( [id] => 5 [type_name] => Mentoring ) [5] => Array ( [id] => 2 [type_name] => Virtual ) [6] => Array ( [id] => 4 [type_name] => Web ) )
2nd print_r returns:
Array ( [2] => Virtual [3] => Instructor Lead/Virtual [4] => Web [1] => Instructor Lead [5] => Mentoring [6] => Independent Study [7] => Job Aid )
Can you print_r($data['training_types']) before the foreach loop and print_r($options) after the loop, and post results? This will help give insight as to what is going into the loop and what is coming out, to make sure it isn't the Form Helper form_dropdown() isn't reordering anything.
My suggestion is to just add a simple asort($options); before the form_dropdown() to insure it is alphabetical.
You didn't specify whether it's Ascending or Descending.
ORDER BY type_name ASC or ORDER BY type_name DESC

Adding a key to a multidimensional array from another multidimensional array

I have seen lots on adding to multidimensional arrays but I can't figure out how they apply to my situation. I am trying to end up with one large multi-dimensional array.
I have a multidimensional associative array compiled from a mysql query of a membership database. All my arrays are compiled using while loops.
Array(
[0] => Array ( [full_name] => Amy Smith [id] => 00111111 [member_ref] => 1 [type] => 1 )
[1] => Array ( [full_name] => Bob Smith [id] => 00222222 [member_ref] => 2 [type] => 0 )
[2] => Array ( [full_name] => Cam Smith [id] => 00333333 [member_ref] => 3 [type] => 2 )
)
This was compiled from the mysql_query
SELECT full_name, id, member_ref, type
FROM members
ORDER BY full_name asc
I then have a list of [id] numbers in another table for people who have paid membership. This is provided by another organisation. This will become the [paid] key.
Array(
[0] => Array ( [id] => 00111111 )
[1] => Array ( [id] => 00333333 )
[2] => Array ( [id] => 00444444 )
)
From query:
SELECT * FROM paid
And finally a table that counts members attendances within a specified timeframe, to be the [log] key.
Array(
[0] => Array ( [member_ref] => 1 [COUNT(member_ref)] => 17 )
[1] => Array ( [member_ref] => 2 [COUNT(member_ref)] => 10 )
[2] => Array ( [member_ref] => 3 [COUNT(member_ref)] => 1 )
)
From
SELECT member_ref, COUNT(member_ref)
FROM log
WHERE timestamp >= STR_TO_DATE('$from')
AND timestamp < STR_TO_DATE('$to')
GROUP BY member_ref
What i want to end up with is: (Note that Bob Smith hasn't paid)
Array(
[0] => Array ( [full_name] => Amy Smith [id] => 00111111 [member_ref] => 1 [type] => 1 [paid] => 00111111 [log] => 17)
[1] => Array ( [full_name] => Bob Smith [id] => 00222222 [member_ref] => 2 [type] => 0 [paid] => 0 [log] => 10)
[2] => Array ( [full_name] => Cam Smith [id] => 00333333 [member_ref] => 3 [type] => 2 [paid] => 00333333 [log] => 1)
)
I can then output it as necessary, but crucuially I can sort the data by any of the keys.
I am open to doing this with a single mysql query with the sort key being a php $var, but I can't figure out the JOIN elements, it's just far too complex for me to understand.
Thanks
Working from the answer of NSjonas:
SELECT m.full_name,
m.id,
m.member_ref,
m.type,
(p.id IS NOT NULL) paid,
COUNT(l.member_ref) log
FROM members m
LEFT JOIN paid p
ON m.id = p.id
LEFT JOIN log l
ON m.member_ref = l.member_ref
AND l.timestamp >= '$from'
AND l.timestamp < '$to'
GROUP BY m.full_name, m.id, m.member_ref, m.type, p.id
ORDER BY m.full_name ASC
My mySQL is a bit rusty but I think this is basically what your looking for. Definitely possible in 1 query
SELECT m.full_name, m.id, m.member_ref, m.type, COUNT(l.member_ref) log,
Case WHEN p.Id != null
THEN true
ELSE false paid
FROM members m
LEFT JOIN paid p
ON m.id = p.id
LEFT JOIN log l
ON m.member_ref = l.member_ref
WHERE l.timestamp >= STR_TO_DATE('$from')
AND l.timestamp < STR_TO_DATE('$to')
ORDER BY m.full_name asc

Categories