MYSQL Query - получить последние комментарии, связанные с сообщением
Я пытаюсь получить последние 1 или 2 комментария, связанные с каждым загружаемым пост, немного похожим на instagram, поскольку они показывают последние 3 комментария для каждого сообщения. До сих пор я получаю сообщения и количество просмотров.
Теперь все, что мне нужно сделать, это выяснить, как получить последние комментарии, не слишком уверенно, как подойти к нему, и именно поэтому я надеюсь, что кто-то с гораздо большим опытом поможет мне!
Это мой текущий запрос:
(SELECT
P.uuid,
P.caption,
P.imageHeight,
P.path,
P.date,
U.id,
U.fullname,
U.coverImage,
U.bio,
U.username,
U.profileImage,
coalesce(Activity.LikeCNT,0),
Activity.CurrentUserLiked
FROM USERS AS U
INNER JOIN Posts AS P
ON P.id = U.id
LEFT JOIN (SELECT COUNT(DISTINCT Activity.uuidPost) LikeCNT, Activity.uuidPost, Activity.id, sum(CASE WHEN Activity.id = $id then 1 else 0 end) as CurrentUserLiked
FROM Activity Activity
WHERE type = 'like'
GROUP BY Activity.uuidPost) Activity
ON Activity.uuidPost = P.uuid
AND Activity.id = U.id
WHERE U.id = $id)
UNION
(SELECT
P.uuid,
P.caption,
P.imageHeight,
P.path,
P.date,
U.id,
U.fullname,
U.coverImage,
U.bio,
U.username,
U.profileImage,
coalesce(Activity.LikeCNT,0),
Activity.CurrentUserLiked
FROM Activity AS A
INNER JOIN USERS AS U
ON A.IdOtherUser=U.id
INNER JOIN Posts AS P
ON P.id = U.id
LEFT JOIN (SELECT COUNT(DISTINCT Activity.uuidPost) LikeCNT, Activity.uuidPost, Activity.id, sum(CASE WHEN Activity.id = $id then 1 else 0 end) as CurrentUserLiked
FROM Activity Activity
WHERE type = 'like'
GROUP BY Activity.uuidPost) Activity
ON Activity.uuidPost = P.uuid
AND Activity.id = U.id
WHERE A.id = $id)
ORDER BY date DESC
LIMIT 0, 5
В основном комментарии хранятся в той же таблице, что и понравилось.
Итак, таблица Activity
, тогда у меня есть столбец comment
, который сохраняет текст комментария, а затем "type" равен "comment".
Возможно, это не очень хорошо объяснено, но я готов попробовать и дать как можно больше деталей!
Если кто-то может помочь ему очень ценится!!
UPDATE
По этому запросу, заданному https://stackoverflow.com/users/1016435/xqbert, я получаю эту ошибку:
Недопустимое сочетание сортировок (utf8_general_ci, IMPLICIT) и (utf8_unicode_ci, IMPLICIT) для операции '='
SELECT Posts.id,
Posts.uuid,
Posts.caption,
Posts.path,
Posts.date,
USERS.id,
USERS.username,
USERS.fullname,
USERS.profileImage,
coalesce(A.LikeCNT,0),
com.comment
FROM Posts
INNER JOIN USERS
ON Posts.id = 145
AND USERS.id = 145
LEFT JOIN (SELECT COUNT(A.uuidPost) LikeCNT, A.UUIDPost
FROM Activity A
WHERE type = 'like'
GROUP BY A.UUIDPOST) A
on A.UUIDPost=Posts.uuid
LEFT JOIN (SELECT comment, UUIDPOST, @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number,@prev_value := UUIDPOST
FROM Activity
CROSS JOIN (SELECT @row_num := 1) x
CROSS JOIN (SELECT @prev_value := '') y
WHERE type = 'comment'
ORDER BY UUIDPOST, date DESC) Com
ON Com.UUIIDPOSt = Posts.UUID
AND row_number <= 2
ORDER BY date DESC
LIMIT 0, 5
Последнее редактирование
Структуры таблиц:
Сообщения
----------------------------------------------------------
| id | int(11) | | not null |
| uuid | varchar(100) | utf8_unicode_ci | not null |
| imageLink | varchar(500) | utf8_unicode_ci | not null |
| date | timestamp | | not null |
----------------------------------------------------------
ПОЛЬЗОВАТЕЛЕЙ
-------------------------------------------------------------
| id | int(11) | | not null |
| username | varchar(100) | utf8_unicode_ci | not null |
| profileImage | varchar(500) | utf8_unicode_ci | not null |
| date | timestamp | | not null |
-------------------------------------------------------------
активность
----------------------------------------------------------
| id | int(11) | | not null |
| uuid | varchar(100) | utf8_unicode_ci | not null |
| uuidPost | varchar(100) | utf8_unicode_ci | not null |
| type | varchar(50) | utf8_unicode_ci | not null |
| commentText | varchar(500) | utf8_unicode_ci | not null |
| date | timestamp | | not null |
----------------------------------------------------------
Вот некоторые примеры, в таблице "Активность" в этом случае "тип" всегда будет равен "комментарий".
Суммируйте все и получите результат:
Когда я запрашиваю сообщения пользователей, я хотел бы иметь возможность зайти в таблицу "Активность" и получить последние 2 комментария за каждое сообщение, которое у него есть. Может быть, комментариев не будет, поэтому, очевидно, он вернет 0, может быть, может быть 100 комментариев для этого сообщения. Но я хочу только получить последние/последние 2 комментария.
В качестве примера можно привести пример использования Instagram. Для каждого сообщения отображаются последние комментарии 1, 2 или 3....
Надеюсь, это поможет!
Ссылка на скрипт
Ответы
Ответ 1
Это сообщение об ошибке
Нелегальное сочетание сортировок (utf8_general_ci, IMPLICIT) и (utf8_unicode_ci, IMPLICIT) для операции '='
обычно определяется определением ваших столбцов и таблиц. Обычно это означает, что по обе стороны от знака равенства есть разные сопоставления. Что вам нужно сделать, это выбрать одно и включить это решение в свой запрос.
Проблема сортировки здесь была в CROSS JOIN из @prev_value, которая нуждалась в явной сортировке, которая будет использоваться.
Я также немного изменил логику "row_number" на одно перекрестное соединение и переместил логику if в крайности списка выбора.
Ниже приведены некоторые примеры данных. Примерные данные необходимы для проверки запросов. Любой, кто пытается ответить на ваш вопрос рабочими примерами, потребует данных. Причина, по которой я включаю его здесь, двояка.
- чтобы вы поняли любой результат, который я представляю
- чтобы в будущем, когда вы задаете другой вопрос, связанный с SQL, вы понимаете важность предоставления данных. Нам не только удобно, что вы это делаете. Если искатель предоставляет образцы данных, то апеллятор уже поймет это - это не будет изобретение какого-то незнакомца, который посвятил часть своего времени, чтобы помочь.
Примеры данных
Обратите внимание, что в таблицах отсутствуют некоторые столбцы, включены только столбцы, указанные в таблице.
В этих образцовых данных имеется 5 комментариев к одному сообщению (записи не поддерживаются)
CREATE TABLE Posts
(
`id` int,
`uuid` varchar(7) collate utf8_unicode_ci,
`imageLink` varchar(9) collate utf8_unicode_ci,
`date` datetime
);
INSERT INTO Posts(`id`, `uuid`, `imageLink`, `date`)
VALUES
(145, 'abcdefg', 'blah blah', '2016-10-10 00:00:00') ;
CREATE TABLE USERS
(
`id` int,
`username` varchar(15) collate utf8_unicode_ci,
`profileImage` varchar(12) collate utf8_unicode_ci,
`date` datetime
) ;
INSERT INTO USERS(`id`, `username`, `profileImage`, `date`)
VALUES
(145, 'used_by_already', 'blah de blah', '2014-01-03 00:00:00') ;
CREATE TABLE Activity
(
`id` int,
`uuid` varchar(4) collate utf8_unicode_ci,
`uuidPost` varchar(7) collate utf8_unicode_ci,
`type` varchar(40) collate utf8_unicode_ci,
`commentText` varchar(11) collate utf8_unicode_ci, `date` datetime
) ;
INSERT INTO Activity (`id`, `uuid`, `uuidPost`, `type`, `commentText`, `date`)
VALUES
(345, 'a100', 'abcdefg', 'comment', 'lah lha ha', '2016-07-05 00:00:00'),
(456, 'a101', 'abcdefg', 'comment', 'lah lah lah', '2016-07-06 00:00:00'),
(567, 'a102', 'abcdefg', 'comment', 'lha lha ha', '2016-07-07 00:00:00'),
(678, 'a103', 'abcdefg', 'comment', 'ha lah lah', '2016-07-08 00:00:00'),
(789, 'a104', 'abcdefg', 'comment', 'hla lah lah', '2016-07-09 00:00:00') ;
[Стандартное поведение SQL: 2 строки для запроса на отправку]
Это был мой первоначальный запрос с некоторыми исправлениями. Я изменил порядок столбцов в списке выбора, чтобы вы могли легко увидеть некоторые данные, связанные с комментариями, когда я представляю результаты. Изучите те результаты, которые они предоставили, чтобы вы могли понять, что будет делать запрос. Столбцы, которым предшествует #, не существуют в образцах данных, с которыми я работаю, по причинам, которые я уже отмечал.
SELECT
Posts.id
, Posts.uuid
, rcom.uuidPost
, rcom.commentText
, rcom.`date` commentDate
#, Posts.caption
#, Posts.path
, Posts.`date`
, USERS.id
, USERS.username
#, USERS.fullname
, USERS.profileImage
, COALESCE(A.LikeCNT, 0) num_likes
FROM Posts
INNER JOIN USERS ON Posts.id = 145
AND USERS.id = 145
LEFT JOIN (
SELECT
COUNT(A.uuidPost) LikeCNT
, A.UUIDPost
FROM Activity A
WHERE type = 'like'
GROUP BY
A.UUIDPOST
) A ON A.UUIDPost = Posts.uuid
LEFT JOIN (
SELECT
@row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
, commentText
, uuidPost
, `date`
, @prev_value := UUIDPOST
FROM Activity
CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci ) xy
WHERE type = 'comment'
ORDER BY
uuidPost
, `date` DESC
) rcom ON rcom.uuidPost = Posts.UUID
AND rcom.row_number <= 2
ORDER BY
posts.`date` DESC
;
См. рабочую демонстрацию этого запроса в SQLFiddle
Результаты:
| id | uuid | uuidPost | commentText | date | date | id | username | profileImage | num_likes |
|-----|---------|----------|-------------|------------------------|---------------------------|-----|-----------------|--------------|-----------|
| 145 | abcdefg | abcdefg | hla lah lah | July, 09 2016 00:00:00 | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah | 0 |
| 145 | abcdefg | abcdefg | ha lah lah | July, 08 2016 00:00:00 | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah | 0 |
Есть 2 ROWS - как и ожидалось. Одна строка для последнего комментария и другие строки для следующего последнего комментария. Это нормальное поведение для SQL и до тех пор, пока в этом ответе не будет добавлен комментарий. Читатели вопроса предполагают, что это нормальное поведение было бы приемлемым.
В вопросе отсутствует четко выраженный "ожидаемый результат".
[Вариант 1: одна строка для каждого запроса на сообщение, с UP TO 2 комментариями, добавленные столбцы]
В приведенном ниже комментарии было показано, что вам не нужно 2 строки за сообщение, и это было бы легко исправить. Ну, это легко, но есть варианты, и параметры продиктованы пользователем в виде требований. Если бы у вопроса был "ожидаемый результат", тогда мы знали бы, какой вариант выбрать. Тем не менее здесь есть один вариант
SELECT
Posts.id
, Posts.uuid
, max(case when rcom.row_number = 1 then rcom.commentText end) Comment_one
, max(case when rcom.row_number = 2 then rcom.commentText end) Comment_two
#, Posts.caption
#, Posts.path
, Posts.`date`
, USERS.id
, USERS.username
#, USERS.fullname
, USERS.profileImage
, COALESCE(A.LikeCNT, 0) num_likes
FROM Posts
INNER JOIN USERS ON Posts.id = 145
AND USERS.id = 145
LEFT JOIN (
SELECT
COUNT(A.uuidPost) LikeCNT
, A.UUIDPost
FROM Activity A
WHERE type = 'like'
GROUP BY
A.UUIDPOST
) A ON A.UUIDPost = Posts.uuid
LEFT JOIN (
SELECT
@row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
, commentText
, uuidPost
, `date`
, @prev_value := UUIDPOST
FROM Activity
CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci ) xy
WHERE type = 'comment'
ORDER BY
uuidPost
, `date` DESC
) rcom ON rcom.uuidPost = Posts.UUID
AND rcom.row_number <= 2
GROUP BY
Posts.id
, Posts.uuid
#, Posts.caption
#, Posts.path
, Posts.`date`
, USERS.id
, USERS.username
#, USERS.fullname
, USERS.profileImage
, COALESCE(A.LikeCNT, 0)
ORDER BY
posts.`date` DESC
;
Посмотрите второй запрос, работающий в SQLFiddle
Результаты запроса 2:
| id | uuid | Comment_one | Comment_two | date | id | username | profileImage | num_likes |
|-----|---------|-------------|-------------|---------------------------|-----|-----------------|--------------|-----------|
| 145 | abcdefg | hla lah lah | ha lah lah | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah | 0 |
** Вариант 2, объедините последние комментарии в один список, разделенный запятыми **
SELECT
Posts.id
, Posts.uuid
, group_concat(rcom.commentText) Comments_two_concatenated
#, Posts.caption
#, Posts.path
, Posts.`date`
, USERS.id
, USERS.username
#, USERS.fullname
, USERS.profileImage
, COALESCE(A.LikeCNT, 0) num_likes
FROM Posts
INNER JOIN USERS ON Posts.id = 145
AND USERS.id = 145
LEFT JOIN (
SELECT
COUNT(A.uuidPost) LikeCNT
, A.UUIDPost
FROM Activity A
WHERE type = 'like'
GROUP BY
A.UUIDPOST
) A ON A.UUIDPost = Posts.uuid
LEFT JOIN (
SELECT
@row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
, commentText
, uuidPost
, `date`
, @prev_value := UUIDPOST
FROM Activity
CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci ) xy
WHERE type = 'comment'
ORDER BY
uuidPost
, `date` DESC
) rcom ON rcom.uuidPost = Posts.UUID
AND rcom.row_number <= 2
GROUP BY
Posts.id
, Posts.uuid
#, Posts.caption
#, Posts.path
, Posts.`date`
, USERS.id
, USERS.username
#, USERS.fullname
, USERS.profileImage
, COALESCE(A.LikeCNT, 0)
ORDER BY
posts.`date` DESC
Посмотрите этот третий запрос, работающий на SQLFiddle
Результаты запроса 3:
| id | uuid | Comments_two_concatenated | date | id | username | profileImage | num_likes |
|-----|---------|---------------------------|---------------------------|-----|-----------------|--------------|-----------|
| 145 | abcdefg | hla lah lah,ha lah lah | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah | 0 |
** Резюме **
Я представил 3 запроса, каждый из которых показывает только два последних комментария, но каждый запрос делает это по-другому. Первый запрос (поведение по умолчанию) отображает 2 строки для каждого сообщения. Вариант 2 добавляет столбец, но удаляет вторую строку. Вариант 3 объединяет два последних комментария.
Обратите внимание:
- В вопросе отсутствуют определения таблиц, охватывающие все столбцы
- В этом вопросе отсутствуют какие-либо образцы данных, что затрудняет вам понимание любых результатов, представленных здесь, но также труднее подготовить решения.
- Вопрос также не содержит окончательного "ожидаемого результата" (желаемого вывода), и это привело к еще большей сложности при ответе на
Я надеюсь, что дополнительная предоставленная информация будет полезна, и что теперь вы также знаете, что для SQL это нормально представлять как несколько строк. Если вы не хотите, чтобы это нормальное поведение, пожалуйста, укажите, что вы действительно хотите в своем вопросе.
Postscript. Чтобы включить еще один подзапрос для "follow", вы можете использовать аналогичный подзапрос для того, который у вас уже есть. Он может быть добавлен до или после этого подзапроса. Вы также можете увидеть его в использовании в sqlfiddle здесь
LEFT JOIN (
SELECT
COUNT(*) FollowCNT
, IdOtherUser
FROM Activity
WHERE type = 'Follow'
GROUP BY
IdOtherUser
) F ON USERS.id = F.IdOtherUser
В то время как добавление другого подзапроса может решить ваше желание получить дополнительную информацию, общий запрос может замедляться пропорционально росту ваших данных. После того как вы определились с функциональностью, в которой вы действительно нуждаетесь, может быть полезно рассмотреть, какие индексы вам нужны для этих таблиц. (Я считаю, что вам будет предложено отдельно спросить этот совет, и если вы убедитесь, что вы включили 1. полный DDL ваших таблиц и 2. план объяснения запроса.)
Ответ 2
Я немного потерял ваш запрос, но если вы хотите загружать данные для нескольких сообщений одновременно, не рекомендуется включать данные комментариев в первый запрос, так как вы будете включать все данные о публикации и публикации пользователь несколько раз. Вы должны запустить другой запрос, который будет связывать сообщения с комментариями. Что-то вроде:
SELECT
A.UUIDPost,
C.username,
C.profileImage,
B.Comment,
B.[DateField]
FROM Posts A JOIN
Activities B ON A.uuid = B.UUIDPost JOIN
Users C ON B.[UserId] = C.id
и использовать эти данные для отображения ваших комментариев с комментариями идентификатора пользователя, имени, изображения и т.д.
Чтобы получить только 3 комментария за сообщение, вы можете посмотреть в этом сообщении:
Выберите верхние 3 значения из каждой группы в таблице с SQL
если вы уверены, что в таблице комментариев или в этом сообщении не будет повторяющихся строк:
Как выбрать верхние 3 значения из каждой группы в таблице с SQL, которые имеют дубликаты
если вы не уверены в этом (хотя из-за DateField в таблице это не должно быть возможно).
Ответ 3
UNTESTED: я бы рекомендовал собрать скрипт SQL с некоторыми примерами данных и существующей структурой таблицы, показывающей проблему; таким образом мы могли бы играть с ответами и обеспечивать функциональность с вашей схемой.
Итак, мы используем переменные для имитации функции окна (типа row_number)
в этом случае @Row_num и @prev_Value. @Row_number отслеживает текущую строку для каждого сообщения (поскольку у одного сообщения может быть много комментариев), тогда, когда встречается новый идентификатор сообщения (UUIDPOST?), Переменная row_num имеет значение reset до 1. Когда текущие записи UUIDPOST соответствует переменной @prev_Value, мы просто увеличиваем строку на 1.
Этот метод позволяет нам назначить номер строки, основанный на дате или порядке идентификатора активности, по убыванию. Поскольку каждое перекрестное соединение приводит только к 1 записи, мы не приводим к появлению повторяющихся записей. Однако, поскольку мы тогда ограничиваем row_number <= 2, мы получаем только два последних комментария в нашем недавно добавленном левом соединении.
Это предполагает, что сообщения, связанные с пользователями, - это много для одного, то есть сообщение может содержать только 1 пользователя.
Что-то вроде этого: хотя я не уверен в последнем левом соединении, мне нужно лучше понять структуру таблицы действий, поэтому комментарий к исходному вопросу.
SELECT Posts.id,
Posts.uuid,
Posts.caption,
Posts.path,
Posts.date,
USERS.id,
USERS.username,
USERS.fullname,
USERS.profileImage,
coalesce(A.LikeCNT,0)
com.comment
FROM Posts
INNER JOIN USERS
ON Posts.id = 145
AND USERS.id = 145
LEFT JOIN (SELECT COUNT(A.uuidPost) LikeCNT, A.UUIDPost
FROM Activity A
WHERE type = 'like'
GROUP BY A.UUIDPOST) A
on A.UUIDPost=Posts.uuid
--This join simulates row_Number() over (partition by PostID, order by activityID desc) (Nice article [here](http://preilly.me/2011/11/11/mysql-row_number/) several other examples exist on SO already.
--Meaning.... Generate a row number for each activity from 1-X restarting at 1 for each new post but start numbering at the newest activityID)
LEFT JOIN (SELECT comment, UUIDPOST, @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number,@prev_value := UUIDPOST
FROM ACTIVITY
CROSS JOIN (SELECT @row_num := 1) x
CROSS JOIN (SELECT @prev_value := '') y
WHERE type = 'comment'
ORDER BY UUIDPOST, --Some date or ID desc) Com
on Com.UUIIDPOSt = Posts.UUID
and row_number < = 2
-- Now since we have a row_number restarting at 1 for each new post, simply return only the 1st two rows.
ORDER BY date DESC
LIMIT 0, 5
нам нужно было поставить строку row_number <= 2 на самом соединении. Если бы он был помещен в предложение where, вы потеряли бы те сообщения без каких-либо комментариев, которые, я думаю, вы все еще хотите.
Кроме того, мы должны, вероятно, посмотреть поле "комментарий", чтобы убедиться, что оно не пустое или пустое, но позволяет убедиться, что это работает в первую очередь.
Ответ 4
Этот тип комментариев был опубликован много раз, и попытка найти "последний для каждого" всегда является камнем преткновения и кошмаром join/subquery для большинства.
Специально для веб-интерфейса вам может быть лучше приклеить столбец (или 2 или 3) к одной таблице, которая является вашей активной таблицей сообщений, такой как Latest1, Latest2, Latest3.
Затем, используя вставку в таблицу комментариев, введите триггер insert в таблицу, чтобы обновить основную запись с помощью нового идентификатора. Тогда у вас всегда есть этот идентификатор на столе без каких-либо подключений. Теперь, как вы упомянули, вы можете захотеть иметь последние 2 или 3 идентификатора, а затем добавить 3 столбца образца и включить триггер вставки для комментариев после комментариев. Обновите основную таблицу сообщений, например
update PrimaryPostTable
set Latest3 = Latest2,
Latest2 = Latest1,
Latest1 = NewDetailCommentID
where PostID = PostIDFromTheInsertedDetail
Это должно быть формализовано в надлежащий триггер в MySQL, но должно быть достаточно простым для реализации. Вы можете перенести список с последним 1, а затем, когда появятся новые сообщения, он автоматически перевернет самые последние в свои 1, 2, 3 позиции. Наконец, ваш запрос может быть упрощен до чего-то вроде
Select
P.PostID,
P.TopicDescription,
PD1.WhateverDetail as LatestDetail1,
PD2.WhateverDetail as LatestDetail2,
PD3.WhateverDetail as LatestDetail3
from
Posts P
LEFT JOIN PostDetail PD1
on P.Latest1 = PD1.PostDetailID
LEFT JOIN PostDetail PD2
on P.Latest2 = PD2.PostDetailID
LEFT JOIN PostDetail PD3
on P.Latest3 = PD3.PostDetailID
where
whateverCondition
Денормализация данных обычно НЕ требуется. Однако в таких случаях он является большим упрощением для получения этих "последних" записей в запросе для каждого типа. Удачи.
Вот полный рабочий пример в MySQL, чтобы вы могли видеть таблицы и результаты sql-вставок и автоматическое тиснение с помощью триггера для обновления главной таблицы сообщений. Затем, запрашивая столбец, вы можете увидеть, как последние автоматически переходят в первую, вторую и третью позиции. Наконец, соединение, показывающее, как вытащить все данные из каждой "активности сообщения"
CREATE TABLE Posts
( id int,
uuid varchar(7),
imageLink varchar(9),
`date` datetime,
ActivityID1 int null,
ActivityID2 int null,
ActivityID3 int null,
PRIMARY KEY (id)
);
CREATE TABLE Activity
( id int,
postid int,
`type` varchar(40) collate utf8_unicode_ci,
commentText varchar(20) collate utf8_unicode_ci,
`date` datetime,
PRIMARY KEY (id)
);
DELIMITER //
CREATE TRIGGER ActivityRecAdded
AFTER INSERT ON Activity FOR EACH ROW
BEGIN
Update Posts
set ActivityID3 = ActivityID2,
ActivityID2 = ActivityID1,
ActivityID1 = NEW.ID
where
ID = NEW.POSTID;
END; //
DELIMITER ;
INSERT INTO Posts
(id, uuid, imageLink, `date`)
VALUES
(123, 'test1', 'blah', '2016-10-26 00:00:00');
INSERT INTO Posts
(id, uuid, imageLink, `date`)
VALUES
(125, 'test2', 'blah 2', '2016-10-26 00:00:00');
INSERT INTO Activity
(id, postid, `type`, `commentText`, `date`)
VALUES
(789, 123, 'type1', 'any comment', '2016-10-26 00:00:00'),
(821, 125, 'type2', 'another comment', '2016-10-26 00:00:00'),
(824, 125, 'type3', 'third comment', '2016-10-27 00:00:00'),
(912, 123, 'typeAB', 'comment', '2016-10-27 00:00:00');
-- See the results after the insert and the triggers.
-- you will see that the post table has been updated with the
-- most recent
-- activity post ID=912 in position Posts.Activity1
-- activity post ID=789 in position Posts.Activity2
-- no value in position Posts.Activity3
select * from Posts;
-- NOW, insert two more records for post ID = 123.
-- you will see the shift of ActivityIDs adjusted
INSERT INTO Activity
(id, postid, `type`, `commentText`, `date`)
VALUES
(931, 123, 'type1', 'any comment', '2016-10-28 00:00:00'),
(948, 123, 'newest', 'blah', '2016-10-29 00:00:00');
-- See the results after the insert and the triggers.
-- you will see that the post table has been updated with the
-- most recent
-- activity post ID=948 in position Posts.Activity1
-- activity post ID=931 in position Posts.Activity2
-- activity post ID=912 in position Posts.Activity3
-- notice the FIRST activity post 789 is not there as
-- anything AFTER the 4th entry, it got pushed away.
select * from Posts;
-- Finally, query the data to get the most recent 3 items for each post.
select
p.id,
p.uuid,
p.imageLink,
p.`date`,
A1.id NewestActivityPostID,
A1.`type` NewestType,
A1.`date` NewestDate,
A2.id SecondActivityPostID,
A2.`type` SecondType,
A2.`date` SecondDate,
A3.id ThirdActivityPostID,
A3.`type` ThirdType,
A3.`date` ThirdDate
from
Posts p
left join Activity A1
on p.ActivityID1 = A1.ID
left join Activity A2
on p.ActivityID2 = A2.ID
left join Activity A3
on p.ActivityID3 = A3.ID;
Вы можете создать тестовую базу данных, чтобы не повредить ваш, чтобы увидеть этот пример.
Ответ 5
Это, вероятно, избавит вас от незаконного сочетания сортировок... После установления соединения выполните этот запрос:
SET NAMES utf8 COLLATE utf8_unicode_ci;
Для вопроса о "последних 2" используйте инструмент командной строки mysql и запустите SHOW CREATE TABLE Posts
и укажите вывод. (То же самое для других соответствующих таблиц.) Phpmyadmin (и другие пользовательские интерфейсы) имеют способ выполнить запрос, не входя в командную строку.
Ответ 6
Вы можете получить там довольно простой запрос, используя подзапросы. Сначала я указываю пользователя в where-clause и присоединяюсь к сообщениям, потому что мне кажется более логичным. Затем я получаю все понравившиеся сообщения для сообщения с суб-запросом.
Теперь вместо группировки и ограничения размера группы мы присоединяем только значения, которые мы хотим, ограничивая количество дат после даты, в которую мы сейчас смотрим.
INNER JOIN Activity, если вы хотите показывать сообщения только с одним комментарием.
SELECT
u.id,
u.username,
u.fullname,
u.profileImage,
p.uuid,
p.caption,
p.path,
p.date,
(SELECT COUNT(*) FROM Activity v WHERE v.uuidPost = p.uuidPost AND v.type = 'like') likes,
a.commentText,
a.date
FROM
Users u INNER JOIN
Posts p ON p.id = u.id LEFT JOIN
Activity a ON a.uuid = p.uuid AND a.type = 'comment' AND 2 > (
SELECT COUNT(*) FROM Activity v
WHERE v.uuid = p.uuid AND v.type = 'comment' AND v.date > a.date)
WHERE
u.id = 145
Тем не менее, редизайн, вероятно, был бы лучшим, а также с точки зрения производительности (активность скоро будет содержать много записей, и их всегда нужно фильтровать для желаемого типа). Таблица пользователей в порядке с автоматическим добавлением идентификатора и в качестве первичного ключа. Для сообщений я также добавлял бы auto-incremented id в качестве первичного ключа и user_id как внешний ключ (вы также можете решить, что делать при удалении, например, с каскадом все его сообщения также будут удалены автоматически).
Для комментариев и комментариев вы можете создавать разделенные таблицы с двумя внешними ключами user_id и post_id (простой пример, например, это могут быть только сообщения и ничего больше, но если их не так много, это все равно может быть полезно создавать post_likes и несколько других..., которые любят таблицы, вам нужно подумать о том, как эти данные обычно запрашиваются, если эти симпатии в основном независимы друг от друга, это, вероятно, хороший выбор).