[英]codeigniter join only most recent row
我正在制作類似於Tindler的約會應用程序,用戶可以互相喜歡或不喜歡。 如果兩個用戶彼此喜歡,則他們應該能夠彼此聊天。 我想出了以下查詢來處理您可以聊天/已與之聊天的用戶的列表-我遇到的問題是我只想提取最新的聊天消息,只是為了在您之前顯示一些內容點擊進入聊天本身。 我的查詢有效,但是它返回最舊的(最低ID)聊天記錄,而不是最新的。 Order by似乎對返回正確結果沒有影響。
$data = $this->db->select('users.id,display_name,city,state,gender,users_pictures.picture,users_chats.message')
->join('users_pictures','users_pictures.user_id=users.id')
->join('users_chats','users_chats.user_id=users.id OR users_chats.foreign_user_id=users.id','left outer')
->where('EXISTS (SELECT 1 FROM users_likes_dislikes ld WHERE (ld.foreign_user_id = '.$this->user_id.' AND ld.user_id=users.id AND ld.event_type=1) OR (SELECT 1 FROM users_likes_dislikes ld WHERE ld.foreign_user_id = users.id AND ld.user_id='.$this->user_id.' AND ld.event_type=1))', '', FALSE)
->where('NOT EXISTS (SELECT 1 FROM users_blocks ub WHERE (ub.foreign_user_id = users.id AND ub.user_id='.$this->user_id.') OR (SELECT 1 FROM users_blocks ub WHERE ub.foreign_user_id = '.$this->user_id.' AND ub.user_id=users.id))', '', FALSE)
->where('((users_chats.user_id='.$this->user_id.' OR users_chats.foreign_user_id='.$this->user_id.') OR (users_chats.user_id is NULL AND users_chats.foreign_user_id is NULL))')
->order_by('users_chats.id','DESC')
->group_by('users.id')
->get('users')
->result_array();
這是users_chats的當前mysql表:
id user_id foreign_user_id message created
1 1 4 test 2013-05-22 15:42:44
2 1 4 test2 2013-05-22 15:44:38
我假設order_by將確保顯示test2消息。
這是示例輸出:
Array ( [0] => Array ( [id] => 4 [display_name] => testinguser [city] => west hills [state] => ca [gender] => 2 [picture] => testasdfasdf.jpg [message] => test ) )
任何幫助深表感謝 :)
編輯-查詢本身(沒有分組依據,這有效,但我需要將其分組到user.id,以便我在數組中沒有針對同一用戶的多個條目):
SELECT
`users`.`id`,
`display_name`,
`city`,
`state`,
`gender`,
`users_pictures`.`picture`,
`users_chats`.`message`
FROM (`users`)
JOIN `users_pictures`
ON `users_pictures`.`user_id` = `users`.`id`
JOIN `users_chats`
ON `users_chats`.`user_id` = `users`.`id`
OR users_chats.foreign_user_id = users.id
WHERE EXISTS(SELECT
1
FROM users_likes_dislikes ld
WHERE (ld.foreign_user_id = 1
AND ld.user_id = users.id
AND ld.event_type = 1)
OR (SELECT
1
FROM users_likes_dislikes ld
WHERE ld.foreign_user_id = users.id
AND ld.user_id = 1
AND ld.event_type = 1))
AND NOT EXISTS(SELECT
1
FROM users_blocks ub
WHERE (ub.foreign_user_id = users.id
AND ub.user_id = 1)
OR (SELECT
1
FROM users_blocks ub
WHERE ub.foreign_user_id = 1
AND ub.user_id = users.id))
AND ((users_chats.user_id = 1
OR users_chats.foreign_user_id = 1)
OR (users_chats.user_id is NULL
AND users_chats.foreign_user_id is NULL))
ORDER BY `users_chats`.`created` DESC
您的group by子句可能是這里的罪魁禍首。 我相信分組操作會首先發生,讓您擁有第一結果。 而不是選擇所有這些行(當有很多噸時,它會花費更長的時間),您應該指定想要的行數-在我看來,無論如何,這都不算太遠。 指定想要的數量,擺脫group by子句,並且由於您具有日期列,因此應按日期排序。 有幫助嗎?
我不確定如何使用db Abstraction進行操作,但是所需的查詢是
SELECT
`users`.`id`,
`display_name`,
`city`,
`state`,
`gender`,
`users_pictures`.`picture`,
chats1.`message`
FROM (`users`)
JOIN `users_pictures`
ON `users_pictures`.`user_id` = `users`.`id`
JOIN `users_chats` AS chats1
ON (chats1.`user_id` = `users`.`id`
OR chats1.foreign_user_id = users.id)
重要的部分到了
AND NOT EXISTS(
SELECT *
FROM users_chats AS chats2
WHERE ((chats2.user_id = chats1.user_id AND chats2.foreign_user_id = chats1.foreign_user_id)
OR (chats2.user_id = chats1.foreign_user_id AND chats1.user_id = chats2.foreign_user_id))
AND chats2.created_date > chats1.created_date --which I assume is a time stamp
)
我知道這不漂亮。
WHERE EXISTS(SELECT 1
FROM users_likes_dislikes ld
WHERE (ld.foreign_user_id = 1
AND ld.user_id = users.id
AND ld.event_type = 1)
OR (SELECT 1
FROM users_likes_dislikes ld
WHERE ld.foreign_user_id = users.id
AND ld.user_id = 1
AND ld.event_type = 1)
)
AND NOT EXISTS(SELECT 1
FROM users_blocks ub
WHERE (ub.foreign_user_id = users.id
AND ub.user_id = 1)
OR (SELECT
1
FROM users_blocks ub
WHERE ub.foreign_user_id = 1
AND ub.user_id = users.id)
)
AND ((chats1.user_id = 1
OR chats1.foreign_user_id = 1)
OR (chats1.user_id is NULL
AND chats1.foreign_user_id is NULL))
ORDER BY `users_chats`.`created` DESC
基本上,只有在沒有其他最新消息時才成功加入。 有一些更好的本機解決方案-TSQL(Microsoft SQL Server)具有CROSS APPLY,在這里會很好-但在不了解您的數據庫層的情況下,我不確定。 您可能需要考慮重新構建聊天結構:
Users(int id /*also other user info*/)
chats(int id, datetime date_initiated, bool /*or bit, or short int*/ is_active)
chat_users (int chat_id, int user_id)
chat_messages (int chat_id, int user_id /*author*/, datetime date_sent, varchar(n) message)
使用這樣的結構,您可以獲取所有如下的最新消息:
SELECT *
FROM Users AS u
INNER JOIN chat_users AS cu
ON u.id = cu.user_id
INNER JOIN chats AS c
ON c.id = cu.chat_id
AND c.is_active = 1
INNER JOIN chat_messages AS m
ON m.chat_id = c.id
AND NOT EXISTS (
SELECT 1
FROM chat_messages AS m2
WHERE m2.chat_id = m.chat_id
AND m.date_sent < m2.date_sent
)
INNER JOIN Users as sender
ON m.user_id = sender.id
WHERE u.id = ###
ORDER BY m.date_sent DESC
您甚至可以創建“聊天最近的消息”視圖,例如:
CREATE VIEW Chat_Recent AS
SELECT * /* WHATEVER YOU LIKE */
FROM chats AS c
INNER JOIN chat_messages AS m
ON m.chat_id = c.id
AND NOT EXISTS (
SELECT 1
FROM chat_messages AS m2
WHERE m2.chat_id = m.chat_id
AND m.date_sent < m2.date_sent
)
INNER JOIN Users as sender
ON m.user_id = sender.id
試試MySQL MAX():
$this->db->join('(SELECT MAX(message) AS lastMsg FROM users_chats WHERE users_chats.user_id=users.id OR users_chats.foreign_user_id=users.id GROUP BY users.id)', 'left outer');
然后在您的選擇上添加“ lastMsg”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.