SQL объединить две таблицы - получить только одну строку для каждого значения ключа - PullRequest
0 голосов
/ 25 марта 2020

Я пытаюсь запустить команду SQL в моей базе данных. У меня есть две таблицы, одна для пользователей, другая для сообщений. Я хочу найти последний пост каждого пользователя. Я попробовал следующее:

SELECT b.`username`, b.`id`, c.`home`, c.`text` FROM `sunlight-users` AS b 
LEFT JOIN `sunlight-posts` AS c ON b.`id` = c.`author`
WHERE b.`group` = 1 OR b.`group`=3 OR b.`group`= 5 OR b.`group` = 10 OR b.`group` = 14 OR b.`group` = 
23 OR b.`group` = 25
ORDER by c.`time` DESC
GROUP BY b.`username`

Сбой из-за ошибки "Ваш синтаксис странный рядом с GROUP BY b. username в строке 5". Я попытался запустить команду с параметром while l oop (на веб-странице) следующим образом:

$query = DB::query("SELECT * FROM `"._mysql_prefix."-users` WHERE `group` = 1 OR `group` = 3 OR `group` = 5 OR `group` = 10 OR `group` = 14 OR `group` = 23 OR `group` = 25");

    while($item = DB::row($query)) {
        $post = DB::query("SELECT type,home,xhome,author,time FROM `"._mysql_prefix."-posts` WHERE ".$knihy." AND `author` = ".item['id']." ORDER BY `time` DESC LIMIT 1");
        switch($post['home']){
            case 2:
           //code
                break;

            case 3:
             //code
            break;

            default:
             //code
        }

Но похоже, что второй запрос полностью игнорируется, я получаю значения по умолчанию, даже если вводить запрос вручную в базу данных попадает 2 или 3. Я знаю, что запускать как 50 запросов в al oop, вероятно, не очень хорошая идея, поэтому я пытаюсь сделать все сразу. Этот код:

SELECT b.`username`, b.`id`, c.`home`, c.`text` FROM `sunlight-users` AS b 
    LEFT JOIN `sunlight-posts` AS c ON b.`id` = c.`author`
    WHERE b.`group` = 1 OR b.`group`=3 OR b.`group`= 5 OR b.`group` = 10 OR b.`group` = 14 OR b.`group` = 
    23 OR b.`group` = 25
    ORDER by c.`time` DESC

приводит к

+----+----------+------+------+
| id | username | home | text |
+----+----------+------+------+
|  1 | user1    |    2 | .... |
|  1 | user1    |    3 | aaaa |
|  0 | user0    |    4 | .... |
+----+----------+------+------+

Порядок правильный, я хочу только верхнюю строку для каждого пользователя. Буду признателен за любую помощь.

1 Ответ

0 голосов
/ 25 марта 2020

Вам на самом деле нужно фильтровать, а не группировать. Вы можете сделать это с помощью коррелированного подзапроса:

select 
    u.username, 
    u.id, 
    p.home, 
    p.text 
from sunlight_users u
left join sunlight_posts p
    on  u.id = p.author
    and p.time = (select max(p1.time) from sunlight_posts p1 where p1.author = u.id)
where u.group in (1, 3, 5, 10, 14, 23, 25)
order by u.username

В MySQL 8.0 вы можете использовать оконные функции:

select *
from (
    select 
        u.username, 
        u.id, 
        p.home, 
        p.text,
        row_number() over(partition by u.id order by p.time desc) rn
    from sunlight_users u
    left join sunlight_posts p on  u.id = p.author
    where u.group in (1, 3, 5, 10, 14, 23, 25)
) t
where rn = 1
order by u.username
...