SQL GROUP CONCAT и LEFT JOIN возвращают только один результат из базы данных

Я пытаюсь запустить SQL-запрос, который может вернуть все сообщения пользователя, а также присоединиться к сообщению, если пользователь прикрепил изображение при отправке сообщения. Но используя приведенный ниже код, он возвращает только данные из post table когда post id за исключением post image id таблица, если не будет игнорировать все сообщения без изображений. Как я могу написать запрос, который возвращает оба сообщения с изображением и без?

Ниже моя структура таблицы

Таблица vendor_account

eu_vendor_id | uname |  mypagename
-------------|-------|--------------
v801         | peter |  pageA
v900         | john  |

Таблица social_posts

social_page_id  |  post_id | vendor_owner_id | post_body_message
----------------|----------|-----------------|------------------------------
pageA           |  p100    |  v801            | This is post without image
pageA           |  p101    |  v801            | This is post with 2 images
pageA           |  p102    |  v801            | This is post with 1 image

Таблица social_post_photos

img | post_image_id | photo_url
----|---------------|---------------
1   | p101          | image1.png
2   | p101          | image2.png
3   | p102          | image01.png

Мой SQL-запрос

SELECT 
im.post_image_id, p.post_body_message,
group_concat(im.photo_url ORDER BY im.photo_url) imgs
FROM social_post_photos im

LEFT JOIN social_posts p
ON p.post_id = im.post_image_id

INNER JOIN vendor_account v
ON p.vendor_owner_id = v.eu_vendor_id

WHERE p.social_page_id = 'pageA'
AND p.vendor_owner_id = 'v801'

GROUP BY im.post_image_id

Текущий результат Когда я запускаю приведенный выше sql-запрос, он возвращает результат, как показано ниже, и игнорирует другой пост, к которому не прикреплено изображение.

post_image_id  |  post_body_message         |  photo_url
---------------|----------------------------|-------------------------
p101           | This is post with 2 images | [IMAGE1.PNG],[IMAGE2.PNG]
p102           | This is post with 1 image  | [IMAGE01.PNG]

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

post_image_id  |  post_body_message         |  photo_url
---------------|----------------------------|-------------------------
p101           | This is post with 2 images | [IMAGE1.PNG],[IMAGE2.PNG]
p102           | This is post with 1 image  | [IMAGE01.PNG]
p100           | This is post without image | null

4 ответа

Решение

Поскольку вы выбираете из social_post_photos вам нужно изменить ваше присоединение к social_posts к RIGHT JOIN чтобы получить все записи из social_posts, Так как я ненавижу RIGHT JOINs, и пока не найдено веских оснований для его использования, я бы вместо этого предложил вам изменить порядок таблиц для выбора social_posts А ТАКЖЕ LEFT JOIN в social_post_photos:

SELECT 
p.post_id, p.post_body_message,
group_concat(im.photo_url ORDER BY im.photo_url) imgs
FROM social_posts p

LEFT JOIN social_post_photos im
ON im.post_image_id = p.post_id
INNER JOIN vendor_account v
ON p.vendor_owner_id = v.eu_vendor_id

WHERE p.social_page_id = 'pageA'
AND p.vendor_owner_id = 'v801'

GROUP BY p.post_id, p.post_body_message

NB При этом вам также нужно выбрать (и сгруппировать по) p.post_id вместо im.post_image_id,

Вы можете попробовать ниже код.

SELECT 
im.post_image_id, p.post_body_message,
group_concat(im.photo_url ORDER BY im.photo_url) imgs
FROM social_posts p

LEFT JOIN social_post_photos im
ON p.post_id = im.post_image_id

INNER JOIN vendor_account v
ON p.vendor_owner_id = v.eu_vendor_id

WHERE p.social_page_id = 'pageA'
AND p.vendor_owner_id = 'v801'

GROUP BY im.post_image_id

Когда LEFT JOIN, переместите правую сторону таблицы условий из WHERE оговорка ON пункт (в противном случае вы получите регулярный INNER JOIN результат):

SELECT 
im.post_image_id, p.post_body_message,
group_concat(im.photo_url ORDER BY im.photo_url) imgs
FROM social_post_photos im

LEFT JOIN social_posts p
ON p.post_id = im.post_image_id
AND p.social_page_id = 'pageA'
AND p.vendor_owner_id = 'v801'

INNER JOIN vendor_account v
ON p.vendor_owner_id = v.eu_vendor_id


GROUP BY im.post_image_id

Не то, что у вас есть инвалид group by, Он не будет выполняться в более новых версиях MySQL (если только не в режиме совместимости), может привести к непредсказуемым результатам со старыми версиями MySQL. Общее правило GROUP BY гласит: если указано предложение GROUP BY, каждая ссылка на столбец в списке SELECT должна либо идентифицировать столбец группировки, либо быть аргументом функции set!

Из вашего поста:

INNER JOIN vendor_account v
ON p.vendor_owner_id = v.eu_vendor_id

Эта часть сократит ваши результаты до 2 максимум, поскольку у вас есть только 1 идентификатор поставщика (peter), который является вашим единственным результатом (я полагаю, что это единственная строка, которую вы получаете).

Для того, чтобы получить обе линии вам нужно LEFT JOIN вместо INNER JOIN последний стол Кроме того, условие Где будет выбирать только один пост и одного поставщика, я не уверен, что вы этого хотите.

SELECT 
im.post_image_id, p.post_body_message,
group_concat(im.photo_url ORDER BY im.photo_url) imgs
FROM social_post_photos im

LEFT JOIN social_posts p
ON p.post_id = im.post_image_id

LEFT JOIN vendor_account v
ON p.vendor_owner_id = v.eu_vendor_id

-- -- I DON'T KNOW IF THIS IS RIGHT?!
-- WHERE p.social_page_id = 'pageA'
-- AND p.vendor_owner_id = 'v801'

GROUP BY im.post_image_id

Вот скрипка со всем, что вам нужно: http://sqlfiddle.com/

Другие вопросы по тегам