簡體   English   中英

codeigniter僅加入最新行

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM