php group array results in single lines - php

Not sure if the title is appropriate for the question, but i have the following problem.
The following code:
while($row = mysql_fetch_array($result2)) {
print_r($row);
}
Produces the following result:
Array
(
[y] => 2016
[m] => 9
[status] => 0
[count] => 2
)
Array
(
[y] => 2016
[m] => 9
[status] => 1
[count] => 33
)
Array
(
[y] => 2016
[m] => 9
[status] => 2
[count] => 4
)
Array
(
[y] => 2016
[m] => 10
[status] => 0
[count] => 20
)
Array
(
[y] => 2016
[m] => 10
[status] => 1
[count] => 3
)
Array
(
[y] => 2016
[m] => 10
[status] => 2
[count] => 14
)
I would like some help with a function that would convert these results to the following format:
Array
(
[y] => 2016
[m] => 9
[<name status 0>] => 2
[<name status 1>] => 33
[<name status 2>] => 4
)
Array
(
[y] => 2016
[m] => 10
[<name status 0>] => 20
[<name status 1>] => 3
[<name status 2>] => 14
)
Any help is greatly appreciated.
This is my first post, so if this post misses important information .. please point it out, and i will add them.
Thank you in advance.
Edit:
The Mysql query:
SELECT y, m, count(status) as count, status
FROM (
SELECT y, m
FROM
(SELECT YEAR(CURDATE()) y UNION ALL SELECT YEAR(CURDATE())-1) years,
(SELECT 1 m UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12) months) ym
LEFT JOIN db_orders
ON ym.y = YEAR(db_orders.delivery_date)
AND ym.m = MONTH(db_orders.delivery_date)
WHERE
(y=YEAR(CURDATE()) AND m<=MONTH(CURDATE()))
OR
(y<YEAR(CURDATE()) AND m>MONTH(CURDATE()))
GROUP BY y, m, status;
Edit 2:
The solution:
editing the select for the mysql query solved my problem:
SELECT y, m, COUNT(IF(status='0',1, NULL)) '', COUNT(IF(status='1',1, NULL)) '', COUNT(IF(status='2',1, NULL)) ''
This leads to the following query:
SELECT y, m, COUNT(IF(status='0',1, NULL)) '<name for status 0>', COUNT(IF(status='1',1, NULL)) '<name for status 1>', COUNT(IF(status='2',1, NULL)) '<name for status 2>'
FROM (
SELECT y, m
FROM
(SELECT YEAR(CURDATE()) y UNION ALL SELECT YEAR(CURDATE())-1) years,
(SELECT 1 m UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12) months) ym
LEFT JOIN db_orders
ON ym.y = YEAR(db_orders.delivery_date)
AND ym.m = MONTH(db_orders.delivery_date)
WHERE
(y=YEAR(CURDATE()) AND m<=MONTH(CURDATE()))
OR
(y<YEAR(CURDATE()) AND m>MONTH(CURDATE()))
GROUP BY y, m, status;

Related

select GROUP_CONCAT in mysql

I have two tables:
table1:
id email
1 john#gmail.com
2 doe#gmail.com
table2:
userid key value
1 firstname john
1 phone 112233
2 firstname doe
2 phone 223344
This is mysql query without condition:
SELECT a.*,
b.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
This is result:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname,phone
[value] => john,112233
)
array(
[id] => 2
[email] => doe#gmail.com
[userid] => 2
[key] => firstname,phone
[value] => doe,223344
)
This is mysql query with condition:
SELECT a.*,
b.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
WHERE b.key = "firstname"
AND b.value LIKE '%jo%'
And this is result:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname
[value] => john
)
But I want this:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname,phone
[value] => john,112233
)
There any way to do this? thank for any help!
Your queries are lacking the GROUP BY clause to get a row per user. Then use a HAVING clause to make sure the aggregated row includes a firstname '%jo%':
SELECT a.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
GROUP BY a.id
HAVING sum(b.key = 'firstname'
AND b.value LIKE '%jo%') > 0;
true results in 1, false in 0 in MySQL. So checking whether the sum is greater than zero means checking whether the condition is true at least once.

Group concat data values by year

I have a query that will sum total loss of data by month within a current year.
SELECT label, m, coalesce(sum(total_loss), 0) as data
FROM (
SELECT label, m
FROM
(
SELECT YEAR(CURDATE()) label UNION ALL SELECT YEAR(CURDATE())-1
) years,
(
SELECT 01 m UNION ALL SELECT 02 UNION ALL SELECT 03 UNION ALL SELECT 04
UNION ALL SELECT 05 UNION ALL SELECT 06 UNION ALL SELECT 07 UNION ALL SELECT 08
UNION ALL SELECT 09 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
) months
) ym
LEFT JOIN incident ON ym.label = YEAR(incident.incident_date) AND ym.m = MONTH(incident.incident_date)
GROUP BY label, m
The data output is
Array
(
[0] => Array
(
[label] => 2017
[m] => 1
[data] => 0
)
[1] => Array
(
[label] => 2017
[m] => 2
[data] => 0
)
[2] => Array
(
[label] => 2017
[m] => 3
[data] => 0
)
[3] => Array
(
[label] => 2017
[m] => 4
[data] => 0
) etc..
This will output all 12 months, and data does not exist will be 0.
What I'm looking for is some sort of group concat that will output something like this:
{
data: [0, 0, 0, 0, 0, 1100, 0, 0, 0, 0, 0, 0],
label: '2017'},
Is it possible to adjust with group concat or write a for each loop to create the data above?
Try grouping only by year, and then use GROUP_CONCAT on the sums across all months:
SELECT
label,
GROUP_CONCAT(COALESCE(SUM(total_loss), 0)) AS data
FROM
(
SELECT label, m
FROM
(
SELECT YEAR(CURDATE()) label UNION ALL SELECT YEAR(CURDATE())-1
) years,
(
SELECT 01 m UNION ALL SELECT 02 UNION ALL SELECT 03 UNION ALL SELECT 04
UNION ALL SELECT 05 UNION ALL SELECT 06 UNION ALL SELECT 07 UNION ALL SELECT 08
UNION ALL SELECT 09 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
) months
) ym
LEFT JOIN incident
ON ym.label = YEAR(incident.incident_date) AND
ym.m = MONTH(incident.incident_date)
GROUP BY label;

How to get the count of each category using group by?

I am using cakephp 2.0 framework. I want to count the number of records of each category.
Here i have two tables
eve_appointment_icons ->having columns- appointment_icon_id,appointment_icon_type_name
eve_appointments ->having columns- id, appointment_icon_id
I have fetch this data using this query:-
$this->EveAppointment->query("SELECT
a.appointment_type
d.appointment_icon_id,
a.appointment_icon_id ,
d.appointment_icon_type_name,
FROM eve_appointments a,
eve_appointment_icons d
WHERE a.appointment_type =1
AND d.appointment_icon_id = a.appointment_icon_id
UNION
SELECT
a.appointment_type
d.appointment_icon_id,
a.appointment_icon_id ,
d.appointment_icon_type_name,
FROM eve_appointments a,
eve_appointment_icons d
WHERE a.appointment_type =2
AND d.appointment_icon_id = a.appointment_icon_id
UNION
SELECT
a.appointment_type
d.appointment_icon_id,
a.appointment_icon_id ,
d.appointment_icon_type_name,
FROM eve_appointments a,
eve_appointment_icons d
WHERE a.appointment_type =3
AND d.appointment_icon_id = a.appointment_icon_id");
Here when I print this:
Array
(
[0] => Array
(
[appointment_icon_id] => 1
[appointment_icon_type_name] => Yoga
)
[1] => Array
(
[appointment_icon_id] => 1
[appointment_icon_type_name] => Yoga
)
[2] => Array
(
[appointment_icon_id] => 2
[appointment_icon_type_name] => Visit
)
[3] => Array
(
[appointment_icon_id] => 3
[appointment_icon_type_name] => Physio Therapy
)
[4] => Array
(
[appointment_icon_id] => 4
[appointment_icon_type_name] => Diagnostic
)
[5] => Array
(
[appointment_icon_id] => 4
[appointment_icon_type_name] => Diagnostic
)
[6] => Array
(
[appointment_icon_id] => 4
[appointment_icon_type_name] => Diagnostic
)
)
Now you can see the Yoga having appointment_icon_id is 1, visit having appointment_icon_id 2 and vice versa for others.
I want count of all these categories.
Like:
appointment_icon_type_name count
Yoga 2
Visit 1
Physio Therapy 1
Diagnostic 3
All you need is this:
select d.appointment_icon_type_name, count(*)
FROM eve_appointments a,
eve_appointment_icons d
WHERE d.appointment_icon_id = a.appointment_icon_id
group by d.appointment_icon_type_name

how to find last message from message table and also find users

This is my User table
This is my Message table
And tHis is my Listing Table
Now I get successfully get the last message with this query
enter code here
$coreQueryUser = $this->Message->query('
select m.*
from
messages m
inner join (
select max(id) as maxid
from messages
where messages.list_id = 3
group By (if(sender_id > reciever_id, sender_id, reciever_id)),
(if(sender_id > reciever_id, reciever_id, sender_id))
) t1 on m.id=t1.maxid
');
when i run this query it gives me following output:-
enter code here
<pre>Array
(
[0] => Array
(
[m] => Array
(
[id] => 2
[sender_id] => 10
[reciever_id] => 21
[list_id] => 3
[message] => hello sir
[add_date] => 2016-09-25 08:24:38
[is_check] => 0
)
)
[1] => Array
(
[m] => Array
(
[id] => 7
[sender_id] => 10
[reciever_id] => 22
[list_id] => 3
[message] => hmm
[add_date] => 2016-09-27 00:00:00
[is_check] => 0
)
)
)
Now you see in the output in first array sender_id =10 and reciver_id = 21
and list_id = 3
List is created by user whose id is 10. in the output i want to fetch the User data whose user id 21. Remember that when reciever send the message to sender the ids are interchanging. in that case i also want the data of whose user id is 21
Please help me:(
Finallly i find the solution of my own
enter code here
$coreQueryUser = $this->Message->query('
select m.* ,u.*
from
messages m
inner join (
select max(id) as maxid
from messages
where messages.list_id = " '. $data['list_id'] .'"
group By (if(sender_id > reciever_id, sender_id, reciever_id)),
(if(sender_id > reciever_id, reciever_id, sender_id))
) t1 on m.id=t1.maxid
join
users u ON u.id = (CASE WHEN m.sender_id = 10
THEN m.reciever_id
ELSE m.sender_id
END)
');

Order by not working with group by clause

I am using corequery of mysql in cakephp. I want the records in descending order. This is my table structure
enter code here
$coreQueryUser = $this->Message->query(
"select * from messages where messages.list_id = 3
group By (if(sender_id > reciever_id, sender_id, reciever_id)),
(if(sender_id > reciever_id, reciever_id, sender_id))
order by id desc
"
);
I want last message that belongs to (sender_id and reciver_id and viceversa) that belongs to list id 3
when i run this query i get the following output
<pre>Array
(
[0] => Array
(
[messages] => Array
(
[id] => 1
[sender_id] => 21
[reciever_id] => 10
[list_id] => 3
[message] => hello
[add_date] => 2016-09-25 00:00:00
[is_check] => 0
)
)
[1] => Array
(
[messages] => Array
(
[id] => 3
[sender_id] => 22
[reciever_id] => 10
[list_id] => 3
[message] => hello s
[add_date] => 2016-09-25 16:39:41
[is_check] => 0
)
)
)
but i wnat result like that:
Array
(
[0] => Array
(
[messages] => Array
(
[id] => 2
[sender_id] => 10
[reciever_id] => 21
[list_id] => 3
[message] => hello sir
[add_date] => 2016-09-25 00:00:00
[is_check] => 0
)
)
[1] => Array
(
[messages] => Array
(
[id] => 6
[sender_id] => 22
[reciever_id] => 10
[list_id] => 3
[message] => new
[add_date] => 2016-09-25 16:39:41
[is_check] => 0
)
)
)
Can anyone help me :(
The problem is that your query is against the sql standard because you have several fields in the select list that are neither in the group by list, nor are subject of an aggregate function, such as sum(). MySQL unfortunately allows such invalid queries to run under certain sql mode settings (the default settings of the most recent versions of MySQL would prevent such queries from running).
As MySQL documentation on group by clause says (bolding is mine):
If ONLY_FULL_GROUP_BY is disabled, a MySQL extension to the standard
SQL use of GROUP BY permits the select list, HAVING condition, or
ORDER BY list to refer to nonaggregated columns even if the columns
are not functionally dependent on GROUP BY columns. This causes MySQL
to accept the preceding query. In this case, the server is free to
choose any value from each group, so unless they are the same, the
values chosen are indeterminate, which is probably not what you want.
Furthermore, the selection of values from each group cannot be
influenced by adding an ORDER BY clause. Result set sorting occurs
after values have been chosen, and ORDER BY does not affect which
value within each group the server chooses.
You apparently want the latest record (with max(id) for each group. The proper way is to have a subquery that returns the max(id) per group and in the outer query join back to your main table using the ids to get the value of the other fields:
select m.*
from
messages m
inner join (
select max(id) as maxid
from messages
where messages.list_id = 3
group By (if(sender_id > reciever_id, sender_id, reciever_id)),
(if(sender_id > reciever_id, reciever_id, sender_id))
) t1 on m.id=t1.maxid
This code working:
SELECT * FROM generate_invoice
WHERE id IN
(
SELECT max(id) as id
FROM generate_invoice
GROUP by pay_id
ORDER by id DESC
)
How to group by DESC order
Try
SELECT * FROM ( SELECT * FROM generate_invoice ORDER BY id DESC ) AS g GROUP BY g.pay_id
OR
Use this code
SELECT m1.*,m2.* FROM generate_invoice m1 LEFT JOIN generate_invoice m2 ON (m1.pay_id = m2.pay_id AND m1.id < m2.id ) order by m1.id desc

Categories