Вопрос

У меня есть запрос MySQL, в который я хочу включить список идентификаторов из другой таблицы.На веб-сайте пользователи могут добавлять определенные товары, а затем добавлять эти товары в избранное.По сути, я хочу получить список идентификаторов людей, которые выбрали этот элемент в избранное (это немного упрощено, но вот к чему все сводится).

В принципе, я делаю что-то вроде этого:

SELECT *,
GROUP_CONCAT((SELECT userid FROM favourites WHERE itemid = items.id) SEPARATOR ',') AS idlist
FROM items
WHERE id = $someid

Таким образом, я мог бы показать, кто выбрал какой-то элемент в избранное, разделив список идентификаторов позже на массив в PHP далее в моем коде, однако я получаю следующую ошибку MySQL:

1242 - Подзапрос возвращает более 1 строки

Я думал, что в этом был своего рода смысл использования GROUP_CONCAT вместо того, чтобы, например, CONCAT?Я иду по этому поводу неправильным путем?


Хорошо, пока спасибо за ответы, кажется, это работает.Однако здесь есть одна загвоздка.Элементы также считаются избранными, если они были добавлены этим пользователем.Поэтому мне понадобилась бы дополнительная проверка, чтобы проверить, является ли creator = userid.Кто-нибудь может помочь мне придумать умный (и, надеюсь, эффективный) способ сделать это?

Спасибо!

Редактировать:Я просто пытался сделать это:

SELECT [...] LEFT JOIN favourites ON (userid = itemid OR creator = userid)

И список идентификаторов пусто.Обратите внимание, что если я использую INNER JOIN вместо того , чтобы LEFT JOIN Я получаю пустой результат.Даже несмотря на то, что я уверен, что есть строки, которые соответствуют требованию ON.

Это было полезно?

Решение

Вы не можете получить доступ к переменным во внешней области видимости в таких запросах (не можете использовать items.id там).Вам лучше попробовать что-то вроде

SELECT
    items.name,
    items.color,
    CONCAT(favourites.userid) as idlist
FROM
    items
INNER JOIN favourites ON items.id = favourites.itemid
WHERE
    items.id = $someid
GROUP BY
    items.name,
    items.color;

Разверните список полей по мере необходимости (название, цвет...).

Другие советы

ОП почти все сделал правильно. GROUP_CONCAT должен заключать столбцы в подзапрос, а не завершите подзапрос (Я отменяю разделитель, потому что по умолчанию используется запятая):

SELECT i.*,
(SELECT GROUP_CONCAT(userid) FROM favourites f WHERE f.itemid = i.id) AS idlist
FROM items i
WHERE i.id = $someid

Это даст желаемый результат, а также означает, что принятый ответ частично неверен, потому что вы можете получить доступ к переменным внешней области в подзапросе.

Я думаю, что у вас может быть неправильный "userid = itemid", разве это не должно быть так:

SELECT ITEMS.id,GROUP_CONCAT(FAVOURITES.UserId) AS IdList
FROM FAVOURITES 
INNER JOIN ITEMS ON (ITEMS.Id = FAVOURITES.ItemId OR FAVOURITES.UserId = ITEMS.Creator)
WHERE ITEMS.Id = $someid
GROUP BY ITEMS.ID

Назначение GROUP_CONCAT верно, но подзапрос не нужен и вызывает проблему.Попробуйте это вместо этого:

SELECT ITEMS.id,GROUP_CONCAT(FAVOURITES.UserId)
FROM FAVOURITES INNER JOIN ITEMS ON ITEMS.Id = FAVOURITES.ItemId
WHERE ITEMS.Id = $someid
GROUP BY ITEMS.ID

Да, решение soulmerge в порядке.Но мне нужен был запрос, в котором я должен был собирать данные из большего количества дочерних таблиц, например:

  • главный стол: сеансы (сеансы презентаций) (uid, имя, ..)
  • 1 - я дочерняя таблица: Мероприятия с ключом session_id (uid, session_uid, дата, time_start, time_end)
  • 2 - я дочерняя таблица: необходимые аксессуары (ноутбук, проектор, микрофоны и т.д.) с ключом session_id (uid, session_uid, accessory_name)
  • 3 - я дочерняя таблица: сессионные_представители (лица, ведущие) с ключом session_id (uid, session_uid, presenter_name, адрес ...)

Каждый сеанс имеет больше строк в дочерних таблицах tables (больше временных графиков, больше аксессуаров)

И мне нужно было собирать в одну коллекцию для каждого сеанса, чтобы отображать в одной строке (некоторые из них):

session_id | session_name | date | time_start | time_end | accessories | presenters

Мое решение (после многих часов экспериментов):

SELECT sessions.uid, sessions.name,
    ,(SELECT GROUP_CONCAT( `events`.date SEPARATOR '</li><li>') 
            FROM `events` 
            WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS date
    ,(SELECT GROUP_CONCAT( `events`.time_start SEPARATOR '</li><li>') 
            FROM `events` 
            WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS time_start
    ,(SELECT GROUP_CONCAT( `events`.time_end SEPARATOR '</li><li>') 
            FROM `events` 
            WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS time_end
    ,(SELECT GROUP_CONCAT( accessories.name SEPARATOR '</li><li>') 
            FROM accessories 
            WHERE accessories.session_id = sessions.uid ORDER BY accessories.name) AS accessories
    ,(SELECT GROUP_CONCAT( presenters.name SEPARATOR '</li><li>') 
            FROM presenters
            WHERE presenters.session_id = sessions.uid ORDER BY presenters.name) AS presenters

    FROM sessions

Так что никакого ОБЪЕДИНЕНИЯ или ГРУППИРОВКИ ПО не требуется.Еще одна полезная вещь для удобного отображения данных (при их "повторении"):

  • вы можете обернуть events.date, time_start, time_end и т.д. в "<UL><LI> ...</LI></UL>" таким образом, "<LI></LI>", используемый в качестве разделителя в запросе, разделит результаты в элементах списка.

Я надеюсь, что это кому-то поможет.Ваше здоровье!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top