I am trying to create a basic notification system. The function below works well, however I'd like to be able to group notifications for the same notification item into the same array item. So, any query result that has the same [item] and [item_id] would be grouped together and just update the count for that item group. So I guess adding a new array item count for that group? I have no idea how to approach this. Any help would be much appreciated.
Query Function:
function get_notifications($connect, $user_id) {
$query = "SELECT * FROM notifications WHERE for_id = {$user_id} AND seen = 0 ";
$result = mysqli_query($connect, $query) or die(mysql_error($connect));
while($row = mysqli_fetch_assoc($result)){
$notifs[] = $row;
}
return $notifs;
}
$notifs = get_notifications($connect, $_SESSION['user_id']);
Current Result:
Array
(
[0] => Array
(
[note_id] => 3
[for_id] => 20
[from_id] => 20
[item] => like_pp
[item_id] => 104
[seen] => 0
[date] => 2022-01-19 12:55:20
)
[1] => Array
(
[note_id] => 4
[for_id] => 20
[from_id] => 20
[item] => like_comment
[item_id] => 332
[seen] => 0
[date] => 0000-00-00 00:00:00
)
[2] => Array
(
[note_id] => 5
[for_id] => 20
[from_id] => 23
[item] => like_pp
[item_id] => 104
[seen] => 0
[date] => 0000-00-00 00:00:00
)
[3] => Array
(
[note_id] => 6
[for_id] => 20
[from_id] => 20
[item] => pp_like
[item_id] => 102
[seen] => 0
[date] => 2022-01-19 15:03:23
)
)
Desired Result: ([item] => like_pp and [item_id] => 104 were the same so combined and updated notification_count)
Array
(
[0] => Array
(
[note_id] => 3
[for_id] => 20
[from_id] => 20
[item] => like_pp
[item_id] => 104
[seen] => 0
[notification_count] => 2
[date] => 2022-01-19 12:55:20
)
[1] => Array
(
[note_id] => 4
[for_id] => 20
[from_id] => 20
[item] => like_comment
[item_id] => 332
[seen] => 0
[notification_count] => 1
[date] => 0000-00-00 00:00:00
)
[2] => Array
(
[note_id] => 6
[for_id] => 20
[from_id] => 20
[item] => pp_like
[item_id] => 102
[seen] => 0
[notification_count] => 1
[date] => 2022-01-19 15:03:23
)
)
I think what you need is a the query that groups by user_id (for who) and item_id (for what type of notif) and delivers the count of this group. Something like:
$query = "SELECT count(*) as notification_count, for_id, item_id FROM notifications WHERE for_id = {$user_id} AND seen = 0 group by for_id, item_id ";
Optionally, if you need in the output the name of the item, for displaying or other purposes, it can be also added:
$query = "SELECT count(*) as notification_count, for_id, item_id, item FROM notifications WHERE for_id = {$user_id} AND seen = 0 group by for_id, item_id, item ";
Use GROUP BY and aggregation functions.
SELECT MIN(note_id) AS note_id, MIN(for_id) AS for_id, MIN(from_id) AS from_id,
item, item_id, MIN(seen) AS seen, COUNT(*) AS notification_count, MIN(date) as date
FROM notifications
WHERE for_id = {$user_id} AND seen = 0
GROUP BY item, item_id
I am creating graph for display month wise count from Mysql database.
Execute this following query:
$cash_query = $this->db->query("select COUNT(*) as count_monthwise, MONTH(FROM_UNIXTIME(dt_added)) as month from `order` where user_id='1' and status != '9' and payment_type = '1' GROUP BY month");
$cash_result = $cash_query->result();
Output:
Array
(
[0] => stdClass Object
(
[count_monthwise] => 1
[month] => 8
)
[1] => stdClass Object
(
[count_monthwise] => 2
[month] => 9
)
)
In above output, there are display "count_monthwise" means count and month "8" means "8th month - August".
But i want to display output with all months, if find count are 0 in any months, then display [count_monthwise] => 0.
I want to display Exact output like:
Array
(
[0] => stdClass Object
(
[count_monthwise] => 1
[month] => 1
)
[1] => stdClass Object
(
[count_monthwise] => 1
[month] => 2
)
.
.
.
.
.
.
.
[10] => stdClass Object
(
[count_monthwise] => 0
[month] => 11
)
[11] => stdClass Object
(
[count_monthwise] => 0
[month] => 12
)
)
I have used using foreach loop something like this, but this is not working.
Loop
foreach($cash_result as $cash => $cash_value){
for($i=0;$i<=11;$i++){
if($i == $cash){
}
}
}
That could be the one way around:
SELECT
COALESCE(yourQuery.count_monthwise,0) AS monthwise_count,
allMonths.month
(SELECT 1 AS month UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12 ) AS allMonths
LEFT JOIN
(
SELECT
COUNT(*) as count_monthwise,
MONTH(FROM_UNIXTIME(dt_added)) as month
from `order`
where user_id='1' and status != '9' and payment_type = '1'
GROUP BY month
) AS yourQuery
ON allMonths.month = yourQuery.month
use below way after getting the result from database don't do complex query just do some code twist
$cash_result = $cash_query->result_array(); // make it to array
$month = range(1,12); // month array
$new_array = array();
$counta = count($month);
for($i=0; $i<$counta ; $i++){
foreach($arr as $key=>$row){
if(($month[$i] == $row['month'])){
$new_array[$i] = $arr[$key];
break;
}else{
$new_array[$i] = array('count_monthwise' => 0,'month' => $month[$i]);
}
}
}
echo '<pre>'; print_r($new_array);
I have a very similar setup to this answer Is there a simpler way to achieve this style of user messaging?
However I'm having an issue with getting the total unread conversations and not unread messages.
SELECT p.conversation_id, COUNT(p.conversation_id) as unread
FROM participation AS p
INNER JOIN messages AS m
ON m.conversation_id = p.conversation_id AND m.seen = 0
WHERE p.uid1 = {$user->data['id']}
GROUP BY m.conversation_id`
I'm only selecting p.conversation_id for testing purposes, but the result I am getting is:
Array
(
[conversation_id] => 1
[unread] => 77
)
If I were to put the results in a PHP while loop I get
Array
(
[conversation_id] => 1
[unread] => 77
)
Array
(
[conversation_id] => 3
[unread] => 7
)
Array
(
[conversation_id] => 8
[unread] => 1
)
Array
(
[conversation_id] => 17
[unread] => 35
)
Array
(
[conversation_id] => 22
[unread] => 2
)
Array
(
[conversation_id] => 24
[unread] => 305
)
Array
(
[conversation_id] => 29
[unread] => 41
)
Array
(
[conversation_id] => 31
[unread] => 1
)
The result I am wanting is unread: 8
I think you just want conditional aggregation:
SELECT p.conversation_id,
SUM(m.seen = 0) as unseen,
SUM(m.seen <> 0) as seen
FROM participation AS p INNER JOIN
messages AS m
ON m.conversation_id = p.conversation_id AND m.seen = 0
WHERE p.uid1 = {$user->data['id']}
GROUP BY m.conversation_id
In addition, if you want the total over all conversations, leave out the group by.
I have a query that returns a list of dates I use for a drop down date picker, here is the SQL query.
SELECT `completion_date`
FROM `enviro_figures_upload`
GROUP BY YEAR( completion_date ) , MONTH( completion_date )
ORDER BY YEAR( completion_date ) ASC , MONTH( completion_date ) ASC
Through phpMyAdmin, the query returns the results I need in the order I need:
2014-01-01
2014-02-01
2014-11-01
2014-12-01
2015-01-01
2015-02-01
In my Symfony2 application, here is the code I use to get this data to my application:
$sql4 = "SELECT `completion_date` FROM `enviro_figures_upload` GROUP BY YEAR(completion_date), MONTH(completion_date) ORDER BY YEAR(completion_date) ASC, MONTH(completion_date) ASC;";
$activeDateSelect = $this->getDoctrine()->getManager()->getConnection()->prepare($sql4);
$activeDateSelect->execute();
$activeDate = $activeDateSelect->fetchAll();
However, the results aren't in the correct order at all. The results that are returned are like this:
2014-01-01
2015-01-01
2014-11-01
2014-12-01
2015-02-01
I can't understand why the results are being changed like this. What can I do?
EDIT
The field type where the date is VARCHAR not DATE. This is because the client I'm building this for can't change the format of the date in Excel which he uses to create the CSV. So the date is uploaded in the UK format, at which point I then reformat the date to the current one.
Here is a var_dump of the fetchAll():
Array
(
[0] => Array
(
[completion_date] =>
)
[1] => Array
(
[completion_date] => 2014-01-06
)
[2] => Array
(
[completion_date] => 2014-02-06
)
[3] => Array
(
[completion_date] => 2014-03-06
)
[4] => Array
(
[completion_date] => 2014-04-06
)
[5] => Array
(
[completion_date] => 2014-05-06
)
[6] => Array
(
[completion_date] => 2014-06-06
)
[7] => Array
(
[completion_date] => 2014-07-06
)
[8] => Array
(
[completion_date] => 2014-08-06
)
[9] => Array
(
[completion_date] => 2014-09-05
)
[10] => Array
(
[completion_date] => 2014-10-05
)
[11] => Array
(
[completion_date] => 2014-11-05
)
[12] => Array
(
[completion_date] => 2014-12-05
)
[13] => Array
(
[completion_date] => 2015-01-01
)
[14] => Array
(
[completion_date] => 2015-02-01
)
[15] => Array
(
[completion_date] => 2015-03-01
)
)
EDIT 2
I iterate the results through Twig like this:
{% for ad in actdate %}
<option value="{{ad.completion_date|date('Y-m')}}">{{ad.completion_date|date('F Y')}}</option>
{% endfor %}
Looking to get a total for each ID from the sum of the replacement fields.
SELECT
insurance_carrier as ID, SUM(REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','')) AS es_reserve,
SUM(REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-',''))AS structure_reserve,
SUM(es_reserve+structure_reserve) AS total
FROM job_tbl
WHERE
job_status NOT IN(2,4,6,7,9) AND
insurance_carrier !=0 AND
FROM_UNIXTIME(date_of_loss,'%m') = MONTH(NOW()) AND
FROM_UNIXTIME(date_of_loss,'%Y') = YEAR(NOW())
GROUP BY insurance_carrier
I get the results from es_reserve and structure_reserve but the total is 0.
BTW the fields contain items like $2,300- that's the reason for the replace
Any help would be appreciated!!!
EDIT: here is the results this produces
Array
(
[ID] => 14
[es_reserve] => 5000
[structure_reserve] => 35000
)
Array
(
[ID] => 15
[es_reserve] => 2500
[structure_reserve] => 2500
)
Array
(
[ID] => 41
[es_reserve] => 2500
[structure_reserve] => 2500
)
Array
(
[ID] => 44
[es_reserve] => 2500
[structure_reserve] =>
)
Here is what I would like it to produce
Array
(
[ID] => 14
[es_reserve] => 5000
[structure_reserve] => 35000
[total] => 40000
)
Array
(
[ID] => 15
[es_reserve] => 2500
[structure_reserve] => 2500
[total] => 5000
)
Array
(
[ID] => 41
[es_reserve] => 2500
[structure_reserve] => 2500
[total] => 5000
)
Array
(
[ID] => 44
[es_reserve] => 2500
[structure_reserve] =>
[total] => 2500
)
Total column is doing sum on original column value , the alias name defined in the select won't be used in the same select.
You can repeat replace statement while doing total column computation
SUM( REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','')
+ REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-',''))
Total,
instead of
SUM(es_reserve+structure_reserve) as total
The query becomes, with order by as asked in comment.
SELECT insurance_carrier as ID, SUM(REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','')) AS es_reserve, SUM(REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-',''))AS structure_reserve, SUM( REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','') + REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-','')) as Total FROM job_tbl WHERE job_status NOT IN(2,4,6,7,9) AND insurance_carrier !=0 AND FROM_UNIXTIME(date_of_loss,'%m') = MONTH(NOW()) AND FROM_UNIXTIME(date_of_loss,'%Y') = YEAR(NOW()) GROUP BY insurance_carrier
order by SUM( REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','') + REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-','')) desc
OR
use it as subquery
SELECT T.*, SUM(es_reserve+structure_reserve) AS total
FROM
(
SELECT
insurance_carrier as ID, SUM(REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','')) AS es_reserve,
SUM(REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-',''))AS structure_reserve
FROM job_tbl
WHERE
job_status NOT IN(2,4,6,7,9) AND
insurance_carrier !=0 AND
FROM_UNIXTIME(date_of_loss,'%m') = MONTH(NOW()) AND
FROM_UNIXTIME(date_of_loss,'%Y') = YEAR(NOW())
GROUP BY insurance_carrier
) T