Order data within group by that has 2 different columns in MySQL - php

I am working with a discussion board where there will be a certain topic and the user can comment or upvote another comment. Each comment can also be replied by another user and will recieve notifications.
My notification table
notification_id is the user_id of the logged in user that will receive the notification
notification_from is the user_id of the one who commented or like the users post.
notification_topic is the id of the topic plus the type of notification that will distinguish if it is a comment or an upvote
notification_comment is the comment_id in the topic
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+
| notification_id | notification_pic | notification_name | notification_title | notification_user_id | notification_date | notification_from | notification_topic | notification_comment | type | status |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+
| 1 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188338 | 32 | 83_upvote | 1 | upvote | read |
| 2 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188342 | 32 | 83_comment | 1 | comment | read |
| 3 | 93_1379990163_thumb.jpg | vhon samson | Chrysler files papers for share sale | 2 | 1380188505 | 93 | 83_upvote | 1 | upvote | read |
| 4 | 93_1379990163_thumb.jpg | vhon samson | Chrysler files papers for share sale | 2 | 1380188509 | 93 | 83_comment | 1 | comment | read |
| 5 | 93_1379990163_thumb.jpg | vhon samson | Chrysler files papers for share sale | 0 | 1380246975 | 93 | 83_comment | 1 | comment | unread |
| 6 | 93_1379990163_thumb.jpg | vhon samson | Toyota and Nissan in vehicle recall | 2 | 1380247149 | 93 | 225_comment | 3 | comment | read |
| 7 | default.gif | kath aguilar | Chrysler files papers for share sale | 2 | 1380253584 | 7 | 83_comment | 1 | comment | read |
| 8 | default.gif | kath aguilar | Chrysler files papers for share sale | 93 | 1380253870 | 7 | 83_comment | 2 | comment | unread |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+
My query
This is how I query and group my table:
SELECT *, COUNT(notification_topic) AS topic_count
FROM tbl_notification
WHERE notification_user_id = '{$_SESSION['id']}'
GROUP BY notification_topic
ORDER BY notification_date DESC
LIMIT 8
This is the result of the query:
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+-------------+
| notification_id | notification_pic | notification_name | notification_title | notification_user_id | notification_date | notification_from | notification_topic | notification_comment | type | status | topic_count |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+-------------+
| 6 | 93_1379990163_thumb.jpg | vhon samson | Toyota and Nissan in vehicle recall | 2 | 1380247149 | 93 | 225_comment | 3 | comment | read | 1 |
| 2 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188342 | 32 | 83_comment | 1 | comment | read | 3 |
| 1 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188338 | 32 | 83_upvote | 1 | upvote | read | 2 |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+-------------+
See it on sqlfiddle.
What I need
I need to get the count so that I can come up with a notification like on facebook, like this:
My main problem is I can't ORDER it by notification_date before the GROUP BY because I need to isolate each notification_comment by its notification_topic. I want the latest user that commented or like each topic to be displayed. How will I do this?

If I've understood your problem correctly then you want the groupwise maximum, which can be obtained by selecting the identifying criteria in the group and then joining back to your table:
SELECT *
FROM tbl_notification NATURAL JOIN (
SELECT notification_topic,
notification_user_id,
MAX(notification_date) AS notification_date,
COUNT(*) AS topic_count
FROM tbl_notification
WHERE notification_user_id = 2
GROUP BY notification_topic,
notification_user_id
) AS t
ORDER BY notification_date DESC
LIMIT 8
See it on sqlfiddle.

Related

How to join other table and count the row in laravel?

I am trying to count how many require position there are for each jobseeker.
I have two tables: jobseeker and jobposition.
jobseeker:
+----+---------+-----------+----------------+
| id | fb_name | fullname | desireposition |
+----+---------+-----------+----------------+
| 1 | John | John Cena | 3 |
| 2 | Christ | Christ | 4 |
| 3 | Thomas | Cfitcher | 2 |
+----+---------+-----------+----------------+
and jobposition:
+----+--------+------------------+
| id | job_id | require_position |
+----+--------+------------------+
| 1 | 12 | 3 |
| 2 | 13 | 3 |
| 3 | 14 | 4 |
| 4 | 15 | 5 |
| 5 | 16 | 4 |
| 6 | 17 | 3 |
+----+--------+------------------+
My expected result is:
+----+---------+-----------+----------------+-----------------------+
| id | fb_name | fullname | desireposition | total_requireposition |
+----+---------+-----------+----------------+-----------------------+
| 1 | John | John Cena | 3 | 3 |
| 2 | Christ | Christ | 4 | 2 |
| 3 | Thomas | Cfitcher | 2 | 0 |
+----+---------+-----------+----------------+-----------------------+
I want to count how many require position there for each jobseeker.
Here is what I tried using crossJoin, but am unsure which join I actually need to be using.
$jobseekers = Jobseeker::crossJoin('jobpositions')
>select('fullname','fb_name','desire_position', DB::raw('count(require_position) as total_requireposition'))
->groupBy('fullname')->paginate(10);
Can anyone help guide me? Any help would be highly appreciated.
The regular MySQL query you want is:
SELECT s.id, fullname, fb_name, desireposition, IFNULL(COUNT(require_position), 0) AS require_position
FROM jobseeker AS s
LEFT JOIN jobposition AS p ON s.desireposition = p.require_position
GROUP BY s.id
I don't use Laravel, but I think the translation would be:
$Jobseeker->select('fullname','fb_name','desire_position', DB::raw('IFNULL(COUNT(require_position), 0) as total_requireposition'))
->leftjoin('jobposition', 'desireposition', '=', 'require_position')
->groupBy('jobseeker.id')
->paginate(10)

How to select mysql results?

invoice
+----+-----+---------+-------+
| Sr | BRN | Name | Amnt |
+----+-----+---------+-------+
| 1 | 1 | John | 10 |
| 2 | 1 | John | 4 |
| 3 | 2 | Belly | 4 |
| 4 | 3 | John | 14 |
| 5 | 4 | John | 5 |
| 6 | 4 | John | 14 |
+----+-----+---------+-------+
I want to select all rows except the duplicate BRN. (If there are two/more ge in BRN then it should only select one)
I tried:
SELECT *(DISTINCT BRN) FROM invoice
Expected result:
+-----+---------+-------+
| BRN | Name | Amnt |
+-----+---------+-------+
| 1 | John | 10 |
| 2 | Belly | 4 |
| 3 | John | 14 |
| 4 | John | 5 |
+-----+---------+-------+
Given the following table:
+----+-----+---------+-------+
| Sr | BRN | Name | Amnt |
+----+-----+---------+-------+
| 1 | 1 | John | 10 |
| 2 | 1 | John | 4 |
| 3 | 2 | Belly | 4 |
| 4 | 3 | John | 14 |
| 5 | 4 | John | 5 |
| 6 | 4 | John | 14 |
+----+-----+---------+-------+
with the expected results:
+-----+---------+-------+
| BRN | Name | Amnt |
+-----+---------+-------+
| 1 | John | 10 |
| 2 | Belly | 4 |
| 3 | John | 14 |
| 4 | John | 5 |
+-----+---------+-------+
The difficult part is getting the amount, because it is arbitrary, not to mention that the values in Amnt are pretty much worthless in this result.
If you want distinct BRN, the query would be SELECT DISTINCT BRN FROM invoice
You might even get away with SELECT DISTINCT BRN, Name FROM invoice
An intermediate step would be SELECT BRN,Name FROM invoice GROUP BY BRN, Name
But if you try to include Amnt in the equation, then the query will fail because there's no way for the database to determine which Amnt to show.
So, you could try this kludge:
SELECT a.BRN, a.Name, b.Amnt FROM invoice AS a LEFT JOIN invoice AS b ON a.BRN=b.BRN
No guarantees on which Amnt it will pick up, though.
Hope that helps.
SELECT * FROM invoice WHERE Date >= :fdate GROUP BY BRN
See Here Use GROUP BY in Query with your Conditions

concat group a SELECT in another SELECT [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Simple question:
There are 2 tables:
Genre [name,songID]
Song [id,title,userID,status]
SELECT id,name,title,userID,status FROM songs INNER JOIN genre ON song.id=genre.songID ORDER BY id ASC;
What is the query to get a result from
+----+-------------+----------------------+--------+--------+
| id | genre.name | song.title | userID | status |
+----+-------------+----------------------+--------+--------+
| 1 | tech | Feel it all | 1 | 1 |
| 2 | tech | Tester | 1 | 1 |
| 3 | music | Sejujurnya | 1 | 1 |
| 4 | music | Not Done | 1 | 1 |
| 5 | life | Cinta | 1 | 1 |
| 6 | life | Feel it all | 1 | 1 |
| 7 | life | Not Done | 1 | 1 |
| 8 | truth | Tester | 1 | 1 |
| 9 | tree | Tester | 1 | 1 |
| 10 | climb | Tester | 1 | 1 |
+----+-------------+----------------------+--------+--------+
to
+----+-------------+---------------------------------+--------+--------+
| id | genre.name | song.title | userID | status |
+----+-------------+---------------------------------+--------+--------+
| 1 | tech | Feel it all,Tester | 1 | 1 |
| 2 | music | Sejujurnya, Not Done | 1 | 1 |
| 3 | life | Cinta, Feel it all, Note Done | 1 | 1 |
| 4 | truth | Tester | 1 | 1 |
| 5 | tree | Tester | 1 | 1 |
| 6 | climb | Tester | 1 | 1 |
+----+-------------+---------------------------------+--------+--------+
Thanks
Use GROUP_CONCAT with GROUP BY
SELECT
id,
genre.name,
GROUP_CONCAT(title) as title,
userID,
status
FROM
songs
INNER JOIN
genre
ON
song.id=genre.songID
GROUP BY
genre.name
ORDER BY
id ASC
SELECT
`Songs`.`id`,
`Genre`.`Name`,
GROUP_CONCAT(`Songs`.`Title`) as Title,
`Songs`.`userID`,
`Songs`.`status`
FROM
`Genre`,
`Songs`
WHERE
`Genre`.`SongID` = `Songs`.`id`
GROUP BY
`Genre`.`Name`

mysql inner join 2 tables and order by count

I am having the following tables in my DB
PROJECTS
+----+-------------------------------------------+
| id | name |
+----+-------------------------------------------+
| 1 | YANNONALI COURT |
| 2 | UNIVERSITY OF COLORARDO DENVER RESEARCH 2 |
| 3 | G.R.E.A.T PROGRAM DESALTER BUILDING |
| 4 | MONARCH CLUB |
| 5 | LAFAYETTE MERCANTILE |
| 6 | CAMELBACK VILLAGE RAQUET AND HEALTH CLUB |
| 7 | BACK COUNTRY |
| 8 | URBAN CRASHPAD |
| 9 | PRIVATE RESIDENCE |
| 10 | EATON RESIDENCE |
+----+-------------------------------------------+
PROJECT_ASSIGNMENTS(WHERE projects.id=project_assignment.target_id)
+-------+-----------+-------------+
| id | target_id | property_id |
+-------+-----------+-------------+
| 19178 | 1 | 48 |
| 19192 | 1 | 39 |
| 19391 | 1 | 3 |
| 19412 | 2 | 3 |
| 19591 | 2 | 34 |
| 19610 | 2 | 34 |
| 21013 | 3 | 2 |
| 21032 | 3 | 2 |
| 30876 | 4 | 2433 |
| 38424 | 5 | 2580 |
+-------+-----------+-------------+
PROPERTIES(WHERE properties.id= project_assignment.property_id)
+----+------------------+
| id | name |
+----+------------------+
| 2 | Residential |
| 3 | Multi Family |
| 34 | New Construction |
| 39 | Contemporary |
| 48 | Southwest |
+----+------------------+
I want O/P ordered by no.of projects in the list...
Residential(177) //12 - total no.of projects which is having this property
Multi Family(15)
New Construction(13)
Contemporary(11)
please give me some MySQL queries
Thank You
This should do the trick:
select
c.name,
count(c.id) as CountOfProperties
from
projects a,
project_assignments b,
properties c
where
a.ID=b.target_id
and b.property_id=c.ID
group by
c.name
order by
count(c.id) desc;
Try this::
select
prop.name,
count(prop.id) as CountOfProperties
from
projects p
inner join project_assignments pa on (p.ID=pa.target_id)
inner join properties prop on (pa.property_id=prop.ID)
group by
prop.name
order by
count(prop.id) desc;

SQL statement to show difference between every user choice and one user choice

Basically I need to create output TOP table where users are arranged by comparing their points with admin's points.
For example:
User3 | 0 //Everything was as admin had.
User5 | 3 //One song had 2 points different from admin and one was off by one
ect.
In my database I have three tables:
Table: rating
+------------+---------+----------+---------+
| rating_id | user_id | song_id | points |
+------------+---------+----------+---------+
| 1 | 1 | 4 | 0 |
| 2 | 1 | 3 | 1 |
| 3 | 3 | 2 | 3 |
| 4 | 4 | 2 | 2 |
| 5 | 2 | 1 | 4 |
Table: songs
+---------------+------------+
| song_name_id | song_name |
+---------------+------------+
| 1 | Song1 |
| 2 | Song2 |
| 3 | Song3 |
| 4 | Song4 |
| 5 | Song5 |
Table: users
+----------+----------+----------+
| id | username | password |
+----------+----------+----------+
| 1 | User1 | passw |
| 2 | User2 | wordp |
| 3 | User3 | somet |
| 4 | User4 | hings |
It should be something like this (not in any programming language):
Compare user_id > 1 with user_id=1 //Let's say that the comparable admin is user_id=1
$result= ABS(user.points-admin.points)++;
And put this to array as:
username => result
Then when I sort this array by result, I can print it as top table - who got the closest result to admin!
I tryed several different solutions but never got the right result.
Can anybody help me?
UPDATE:
Thanks!
With JOIN the result is:
+------------+---------+----------+---------+-----------+
| song_id |song_name| user_id |username |rating_diff|
+------------+---------+----------+---------+-----------+
| 1 | Song1 | 1 | admin | 0 |
| 2 | Song2 | 1 | admin | 0 |
...etc...
With LEFT JOIN the result is:
+------------+---------+----------+---------+-----------+
| song_id |song_name| user_id |username |rating_diff|
+------------+---------+----------+---------+-----------+
| 1 | Song1 | 11 | user2 | NULL |
| 1 | Song1 | 10 | user1 | NULL |
| 1 | Song1 | 12 | user3 | NULL |
| 1 | Song1 | 1 | admin | 0 |
| 2 | Song2 | 11 | user2 | NULL |
| 2 | Song2 | 10 | user1 | NULL |
| 2 | Song2 | 12 | user3 | NULL |
| 2 | Song2 | 1 | admin | 0 |
..etc..
So.. Something is wrong, the rating_diff does not work.
Assuming you want this comparison on a song-by-song basis (instead of a total or average across all songs), try:
select r.song_id,
s.song_name,
r.user_id,
u.username,
abs(r.points - r1.points) rating_diff
from rating r
join songs s on r.song_id = s.song_name_id
join users u on r.user_id = u.id
join rating r1 on r.song_id = r1.song_id and r1.user_id = 1
order by s.song_name, abs(r.points - r1.points)
This should sort the output by the song name, and then by the difference between the admin's points and the users' points. (Change the join on rating r1 to be a left join if you can't guarantee an admin rating for every song.)

Categories