Mysql ORDER BY or GROUP BY for newsfeed - mysql

I want to create something like Facebook newsfeed: a person who follows other persons see their last posts at the top. I use this query as db select query but it has some problem.
Does anyone have any idea to improve this query?
These are important tables for this query:
______
| wall |
-------------------------------------------------------------------------------------
postID | inserterID | sportID | catID | title|insertDate|context|abstraction|editeDate
-------------------------------------------------------------------------------------
|follower|
---------------------
ID | foerID | foingID
---------------------
SELECT wall.postID
, wall.inserterID
, wall.title
, wall.insertDate
, wall.editDate
, wall.context
, user.lastName
, cat.catName
, wall.catID
, pic.picname AS pic
, foerID
FROM wall
JOIN user
ON user.userID = wall.inserterID
JOIN postcategory cat
ON cat.catID = wall.catID
LEFT
JOIN wallpic pic
ON pic.postID = wall.postID
LEFT
JOIN follow
ON follow.foingID = wall.inserterID
WHERE wall.inserterID != 71
GROUP
BY wall.postID
ORDER
BY follow.foerID IN (71) DESC
, wall.insertDate DESC
LIMIT 0,100

Related

How to SUM Duplicate COUNT values in Mysql

I have this code:
Const SQLExpression As String = "SELECT site.siteid AS 'SITE ID', site_name AS 'SITE', COUNT(DISTINCT date) AS 'Attendance', 75 * (SELECT COUNT(DISTINCT date) AS 'Attendance') AS 'Total' FROM record LEFT JOIN learner on record.idNumber = learner.idNumber LEFT JOIN site ON learner.siteid=site.siteid WHERE MONTH(date) = MONTH(CURRENT_DATE()) AND YEAR(date) = YEAR(CURRENT_DATE()) GROUP BY record.idNumber "
And it returns the following data: Table
I want to to get the following:
+----------+--------------------------------+
| SITE ID | SITE | Attendance |
+-------------------------------------------+
| 314 | Broad Market1 | 34 |
| 254 | Catherine Booth.. | 36 |
| 289 | Ceter for Entrep..| 27 |
| 330 | Climamark Morem.. | 7 |
+-------------------------------------------+
I have tried the following code:
"SELECT siteid AS 'SITE ID', site_name AS 'SITE', SUM(DISTINCT Attendance) AS 'Attendance' FROM (SELECT COUNT(DISTINCT record.date)AS 'Attendance' FROM record LEFT JOIN learner on record.idNumber = learner.idNumber LEFT JOIN site ON learner.siteid=site.siteid WHERE MONTH(date) = MONTH(CURRENT_DATE()) AND YEAR(date) = YEAR(CURRENT_DATE()) GROUP BY record.idNumber) As Attendance, site GROUP BY siteid "
Am getting the following data: TableResult
Assuming that in the table site you have id for primary key you should use a inner join INNER JOIN site Attendance.siteid = site.id (and not a cross join (Attendance, site without where) )
"SELECT siteid AS 'SITE ID'
, site_name AS 'SITE'
, SUM(DISTINCT Attendance) AS 'Attendance'
FROM (
SELECT COUNT(DISTINCT record.date) AS 'Attendance'
FROM record
LEFT JOIN learner on record.idNumber = learner.idNumber
LEFT JOIN site ON learner.siteid=site.siteid
WHERE MONTH(date) = MONTH(CURRENT_DATE())
AND YEAR(date) = YEAR(CURRENT_DATE())
GROUP BY record.idNumber ) As T_Attendance
INNER JOIN site T_Attendance.siteid = site.id
GROUP BY siteid "

PHP MySQL SELECT newest entry grouped by an ID and ordered by timestamp

I am working on an problem regarding Selecting data from two MySQL tables.
First table holds messages | messages | (id, msg_group_id, to_user_id, from_user_id, datetime)
Second table holds user data | profiles | (user_id, name, firstname, ...)
ATM it works the way, that I can select ALL messages with a certain 'to_id' and by adding a JOIN statement getting the name and firstname of the user who sends the message.
My problem now is that I can not figure out a way to ONLY select the newest message of a certain msg_group_id.
I already tried GROUP BY msg_group_id combined with ORDER BY datetime DESC.
But that only throws the very first entry in message table. But I want to last one. :-)
I hope you can help me. :-)
My actual SQL statement:
SELECT LEFT(messages.message, 10) AS message,
`messages`.`msg_group_id`,
`messages`.`datetime`,
`profiles`.`name`,
`profiles`.`firstname`
FROM `messages`
LEFT JOIN `profiles`
ON `messages`.`from_user_id` = `profiles`.`user_id`
WHERE `to_user_id` = '2'
ORDER BY `datetime` DESC
LIMIT 20;
Thanks in Advance
Sample INPUT:
[messages]
|id|msg_group_id|to_user_is|from_user_id|message |datetime|
0 | 1 | 1 | 2 | Hello World1 | 2015-12-21 10:42:00
1 | 1 | 1 | 2 | Hello World2 | 2015-12-21 10:43:00
2 | 1 | 1 | 2 | Hello World3 | 2015-12-21 10:44:00
[profiles]
user_id|name |firstname|
1 | Test | User
2 | Thanks | Worldname
Result (what I don't want)
message|msg_group_id|datetime|name|firstname
Hello World1 | 1 | 2015-12-21 10:42:00 | Thanks | Worldname
Result (what I want)
message|msg_group_id|datetime|name|firstname
Hello World3 | 1 | 2015-12-21 10:44:00 | Thanks | Worldname
May be this query can help:
SELECT m.message, m.msg_group_id, m.datetime, u.name, u.firstname
FROM message as m, profiles as u
WHERE m.from_user_id = u.user_id
GROUP BY m.msg_group_id
ORDER BY m.datetime DESC
Or use INNER JOIN
SELECT m.message, m.msg_group_id, m.datetime, u.name, u.firstname
FROM message as m
INNER JOIN profiles as u ON m.from_user_id = u.user_id
GROUP BY m.msg_group_id
ORDER BY m.datetime DESC
I guess I solved the Problem with the help of another thread:
https://stackoverflow.com/a/1313140/4493030
My SQL Statement as follows:
SELECT `messages`.*, `profiles`.`nick_name`
FROM `messages`
LEFT JOIN `profiles`
ON `messages`.`from_user_id` = `profiles`.`user_id`
INNER JOIN
(SELECT konversation_id, MAX(id) AS maxid FROM messages
WHERE messages.to_user_id = 2
GROUP BY konversation_id) AS b
ON messages.id = b.maxid
WHERE `to_user_id` = '2'
ORDER BY `datetime` DESC
LIMIT 20;
Thanks to all of you who tried to help.
I found a way to tight it down
SELECT messages.to_user_id, messages.msg_group_id, MAX(messages.id) AS maxid, messages.from_user_id, profiles.name
FROM messages
LEFT JOIN profiles
ON messages.from_user_id = profiles.user_id
WHERE messages.to_user_id = 2
GROUP BY msg_group_id

Inner join with where

I need to get Max bid and that username but result is coming in wrong way
Here is my two tables
Product
id | name | username
1 | A | deen
2 B | ann
Bid
id | c_bid | username
1 | 10 | ann
1 | 12 | ann
1 | 13 | ann
2 | 10 | ann
1 | 15 | Hel
1 | 16 | Hel
SQL
SELECT name, bid.username AS username, MAX(bid.c_bid) AS c_bid FROM product INNER JOIN bid
ON gems.id= bidding.id WHERE bid.id = '1'
Result
name | c_bid | username
A | 16 | ann
Why is this result coming on this sql?
Since you are using an aggregate function you need to include a GROUP BY.
SELECT name,
bid.username AS username,
MAX(bid.c_bid) AS c_bid
FROM product
INNER JOIN bid
ON product.id= bid.id
WHERE bid.id = '1'
GROUP BY name, bid.username
See SQL Fiddle with Demo
You are getting strange results because MySQL uses an Extension to GROUP BY that allows you to use an aggregate function without using a GROUP BY but this could cause your result to be incorrect.
The GROUP BY makes it so you will return the max(bid) for each item that you are grouping by, in your case it is name and `username.
If you want to return only one max(bid) for each product id, then you could use:
SELECT name,
bid.username AS username,
bid.c_bid
FROM product
INNER JOIN bid
ON product.id= bid.id
INNER JOIN
(
SELECT max(c_bid) c_bid, id
FROM bid
GROUP BY id
) b
on bid.id = b.id
and bid.c_bid = b.c_bid
WHERE bid.id = '1'
See SQL Fiddle with Demo
Use GROUP BY.
SELECT name, bid.username AS username, MAX(bid.c_bid) AS c_bid FROM product INNER JOIN bid
ON gems.id= bidding.id WHERE bid.id = '1' GROUP BY bid.username;
SELECT
p.username,
MAX(b.c_bid) AS max_c_bid
FROM product p
LEFT JOIN bid b ON (p.username = b.username)
GROUP BY p.username;
SELECT
pr.name,
mb.c_bid,
pr.username
FROM
(
SELECT
SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY c_bid DESC), ',', 1) AS id,
MAX(c_bid) AS c_bid
FROM bid
GROUP BY id
) AS mb
JOIN product AS pr ON(pr.id = mb.id)
Example: http://sqlfiddle.com/#!2/0a6c9/2

My SQL query is failing to get low cost rooms at multiple rooms bookings

Bellow is my "rooms" mysql table. (This is example table i have created to show here.)
I want to show low cost rooms in case multiple room bookings. Ex: User have select two room, 1 adult in first room and 2 adults in second room. Now my result should come as below
My Query is : SELECT * FROM rooms WHERE hotel_code="100" GROUP BY adult+child Order by cost ASC
It is not working. I am not able to get the expected result with this query. Please let me know the solution for this.
Try this:
SELECT r.*
FROM Rooms r
INNER JOIN
(
SELECT
adult, child, MIN(Cost) MinCost
FROM Rooms
WHERE hotel_code = 100
GROUP BY adult, child
) m ON r.adult = m.adult AND r.child = m.child
AND r.cost = m.mincost
ORDER BY r.id
LIMIT 2;
SQL Fiddle Demo
This will give you:
| ID | HOTEL_CODE | ROOM_TYPE | ADULT | CHILD | COST |
---------------------------------------------------------
| 2 | 100 | Single Delux | 1 | 0 | 20 |
| 3 | 100 | Twin Stadard | 2 | 0 | 25 |
Extending Mahmoud's thinking with a (less scalable) extension...
SELECT a.*
FROM
( SELECT x.*
FROM rooms x
JOIN
( SELECT hotel_code
, adult
, child
, MIN(cost) min_cost
FROM rooms
GROUP
BY hotel_code
, adult
, child
) y
ON y.hotel_code = x.hotel_code
AND y.adult = x.adult
AND y.child = x.child
AND y.min_cost = x.cost
) a
LEFT
JOIN
( SELECT x.*
FROM rooms x
JOIN
( SELECT hotel_code
, adult
, child
, MIN(cost) min_cost
FROM rooms
GROUP
BY hotel_code
, adult
, child
) y
ON y.hotel_code = x.hotel_code
AND y.adult = x.adult
AND y.child = x.child
AND y.min_cost = x.cost
) b
ON b.hotel_code = a.hotel_code
AND b.adult = a.adult
AND b.child = a.child
AND b.cost = a.cost
AND b.id < a.id
WHERE b.id IS NULL;

problem with query

what i am trying:
SELECT
`update_photo`,
(SELECT substring_index (`username`, ' ', 1)),
`id_user`
FROM users
JOIN worker_has_profession
ON worker_has_profession.worker_single_user_users_id_user = users.id_user
ORDER BY `registration`
DESC LIMIT 10
The output will be:
path photo | John | 31
but i need something like this (profession is in another table)
path photo | John | 31 | designer
Tables
<table worker_has_profession>
worker_single_user_users_id_user //same id of id_user
profession_id_profession
worker_single_user_users_id_user profession_id_profession
31 10
<table profession>
id_profession
profession
id_profession profession
10 designer
Any idea?
Added the join below and profession to select list.
SELECT
update_photo,
(SELECT substring_index (`username`, ' ', 1)),
U.id_user,
P.profession
FROM users U
JOIN worker_has_profession WP
ON WP.worker_single_user_users_id_user = U.id_user
JOIN profession P
ON P.id_profession = WP.profession_id_profession
ORDER BY registration
DESC LIMIT 10