无法在我的查询

时间:2017-11-18 02:46:55

标签: mysql sql

您好我正在使用下面的查询从每个唯一对话中选择最新消息。除非我尝试整合INNER JOIN以尝试将用户的user_idusername表格中的users相关联,否则一切都会完美无缺。

我已经尝试了几乎所有组合来集成INNER JOIN所以我决定将它与工作查询分开,直到我得到帮助。

我做了一个小提琴 http://sqlfiddle.com/#!9/a9bbc/1我只想让右边的user_id打印用户的用户名

SELECT message_id, 
       msg, 
       user_id 
FROM   messages 
   JOIN (SELECT user_id, 
                Max(dat) m 
         FROM   ((SELECT message_id, 
                         recipient_id user_id, 
                         dat 
                  FROM   messages 
                  WHERE  owner_id = 1) 
                 UNION 
                 (SELECT message_id, 
                         owner_id user_id, 
                         dat 
                  FROM   messages 
                  WHERE  recipient_id = 1)) t1 
         GROUP  BY user_id) t2 
     ON ( ( owner_id = 1 
            AND recipient_id = user_id ) 
           OR ( owner_id = user_id 
                AND recipient_id = 1 ) ) 
        AND ( dat = m ) 
 ORDER  BY dat DESC

users.username INNER JOIN users ON messages.user_id = users.user_id;

5 个答案:

答案 0 :(得分:1)

我认为这是正确的......最后。不存在在开始后过滤掉响应。内部查询抓取最近的对话。这应该与预期的输出相匹配。

SELECT dT.maxid AS message_id
      ,(SELECT msg FROM messages M WHERE M.message_id = dT.maxid) AS message_id
      ,(SELECT username FROM users U WHERE U.user_id = dT.owner_id) AS user_id      
  FROM (  
         SELECT MAX(message_id) as maxid
               ,owner_id
               ,recipient_id
           FROM messages M
         GROUP BY owner_id, recipient_id
       ) AS dT
WHERE NOT EXISTS(SELECT *
                   FROM messages M2
                  WHERE M2.recipient_id = dT.owner_id
                    AND M2.owner_id = dT.recipient_id
                    AND M2.message_id > dT.maxid)
ORDER BY dT.maxid        

产生输出:

message_id  message_id                                             user_id
8           you should Now see this instead even with the          User2
            owner_id flipped.. The users_id in the query is 1 
            and it gets the conversation with user_id 2 
9           You should also see this                               User1

fiddle

答案 1 :(得分:1)

如果messages.message_idAUTO_INCREMENT PRIMARY KEY列,这可能是获得所需结果的最快方式:

select m.message_id, m.msg, u.username,
  case sub.other_user_id
    when m.owner_id     then 'received from'
    when m.recipient_id then 'sent to'
  end as direction
from (
  select other_user_id, max(message_id) as message_id
  from (
    select recipient_id as other_user_id, max(message_id) as message_id
    from messages
    where owner_id = @uid
    group by recipient_id

    union all

    select owner_id as other_user_id, max(message_id) as message_id
    from messages
    where recipient_id = @uid
    group by owner_id
  ) sub
  group by other_user_id
) sub
join messages m on m.message_id = sub.message_id
join users u    on u.user_id    = sub.other_user_id
order by sub.message_id desc

我还添加了专栏direction。这样您就可以知道消息是否已发送或接收。结果如下:

| message_id |                                                              msg | username |     direction |
|------------|------------------------------------------------------------------|----------|---------------|
|          9 | You should also see this                                         |    User3 |       sent to |
|          8 | you should Now see this instead even with the owner_id flipped.. |    User2 | received from |

http://sqlfiddle.com/#!9/a9bbc/34

请注意,您仍然可以在SELECT子句中的usersmessages表中添加任何列。

要让此查询快速运行,您需要messages(owner_id, recipient_id)messages(recipient_id, owner_id)上的索引。

答案 2 :(得分:0)

当你加入任何表或子查询时,你真的真的需要包含所有列引用的表名或表别名。我将最大数据更改为maxdat,因此我可以使用m作为消息。

declare @oq nvarchar(max) = N'prefix_'
declare @cmd nvarchar(max)
select @cmd = a from (
    select 'EXEC sp_rename ''' + TABLE_NAME + ''', ''' + REPLACE(TABLE_NAME, @oq, N'') + ''' '
    from INFORMATION_SCHEMA.TABLES
    for xml path('')
) t(a)
exec sp_executesql @cmd

答案 3 :(得分:0)

如果我理解正确,您需要发送或收件人为“1”的最新邮件以及相关的用户名。

这表明:

SELECT
      m.message_id
    , m.msg
    , m.user_id
FROM messages m
JOIN (
      SELECT
            user_id
          , MAX(dat) maxdat
      FROM (
            (SELECT
                  message_id
                , recipient_id user_id
                , dat
            FROM messages
            WHERE owner_id = 1)
            UNION
            (SELECT
                  message_id
                , owner_id user_id
                , dat
            FROM messages
            WHERE recipient_id = 1)
      ) t1
      GROUP BY
            user_id
) t2 ON (
         (m.owner_id = 1 AND m.recipient_id = t2.user_id)
      OR (m.owner_id = t2.user_id AND m.recipient_id = 1)
        )
      AND (m.dat = t2.maxdat)
ORDER BY
      m.dat DESC

编辑:

基于您的SQL Fiddle,上述理解不正确。你想考虑成对的收件人,所以我想你想要:

select m.*, ur.username as recipient_name, us.username as sender_name
from messages m join
     users ur
     on m.recipient_id = ur.user_id join
     users us
     on m.sender_id = us.user_id
where m.date = (select max(m2.dat)
                from messages m2
                where 1 in (m2.recipient_id, m2.sender_id)
               ) and
      1 in (m.recipient_id, m.sender_id);

Here是SQL小提琴。

如果对的排序是导入的(因此select m.*, ur.username as recipient_name, us.username as sender_name from messages m left join users ur on m.recipient_id = ur.user_id left join users us on m.owner_id = us.user_id where m.dat = (select max(m2.dat) from messages m2 where (m2.recipient_id, m2.owner_id) = (m.recipient_id, m.owner_id) or (m2.recipient_id, m2.owner_id) = (m.owner_id, m.recipient_id) ) and 1 in (m.recipient_id, m.owner_id); (1, 2)不同,请删除最里面的(2, 1)子句中的第二个条件。

答案 4 :(得分:0)

您需要使用users表加入最终结果,并根据user_id获取users.username的值。试试这个:

SELECT messages.message_id, 
   messages.msg,
   users.user_id,
   users.username   
FROM   users, messages 
  JOIN (SELECT user_id, 
            Max(dat) m 
     FROM   ((SELECT message_id,
                     users.username,
                     recipient_id user_id, 
                     dat 
              FROM   messages
              INNER JOIN users ON messages.recipient_id = users.user_id
              WHERE  owner_id = 1) 
             UNION 
             (SELECT message_id,
                     users.username,
                     owner_id user_id, 
                     dat 
              FROM   messages
               INNER JOIN users ON messages.owner_id = users.user_id
              WHERE  recipient_id = 1)) t1 
     GROUP  BY user_id) t2 
 ON ( ( owner_id = 1 
        AND recipient_id = user_id ) 
       OR ( owner_id = user_id 
            AND recipient_id = 1 ) ) 
    AND ( dat = m ) 
WHERE users.user_id = messages.user_id
ORDER  BY dat DESC