Передача аргумента в LEFT JOIN

В настоящее время я пытаюсь получить данные из 2 таблиц с LEFT JOIN, имеющим неизвестное значение.

Я пытался использовать LEFT JOIN, но это не сработало.

Вот мой пример кода:

SELECT 
    cc.shid,
    cc.user,
    ts.type,
    sum(cc.qty1) + sum(cc.qty2) as qty_tot,
    COUNT(cc.id) as nb
FROM
    content_c cc
LEFT JOIN
    (SELECT
        s.shid,
        s.type
    FROM
        tab_s s
    LIMIT 1
    ) as ts ON ts.shid = cc.shid
WHERE 
    cc.time_i like '2019-01%'
GROUP BY 
    cc.user,
    ts.type

С этим запросом он никогда не будет работать: ts будет содержать первое вхождение tab_s независимо от cc.shid. Интересно, есть ли способ сделать это:

LEFT JOIN
    (SELECT
        s.shid,
        s.type
    FROM
        tab_s s
    WHERE
        s.shid = cc.shid
    LIMIT 1
    ) as ts ON ts.shid = cc.shid

Есть идеи ? Есть ли в SQL понятие указателя или что-то в этом роде? Например, я могу использовать &cc.shid или @cc.shid?

Обратите внимание, что выполните следующие действия:

LEFT JOIN tab_s ts ON ts.shid = cc.shid

Заставит мой запрос занять более 1 минуты, чтобы отобразить результаты. И я не могу установить индекс в tab_s.shid, а также в cc.shid, поскольку он имеет несколько вхождений.

Пожалуйста, имейте в виду, что content_c может иметь несколько вхождений cc.shid, поэтому мне нужно взять только первый результат (LIMIT 1). Это важно.

Индексы не обязательно должны быть уникальными. Вы можете легко проиндексировать tab_s.shid

Martin 28.05.2019 11:26

Трудно сказать, что вы пытаетесь сделать из запроса, который не работает, но я предполагаю, что у вас есть, например, Пользователи и Адреса, и может быть несколько адресов, но только последний (определенный какой-то датой) адрес "текущий" «Итак, вы пытаетесь получить список пользователей и их текущий адрес, а у некоторых пользователей могут не быть записанных адресов, поэтому вам нужно левое соединение. Это что-то близкое к тому, что вы пытаетесь сделать? Разместите, пожалуйста, образцы данных в таблицах

Caius Jard 28.05.2019 11:40

LIMIT 1 приводит к тому, что из подзапроса возвращается только одна общая строка, а не одна строка на идентификатор. Какой столбец позволяет определить, является ли конкретная строка в content_c первой? Например, минимальная/максимальная дата или что-то в этом роде. (Надеюсь, вы не скажете: «О, это может быть любая строка, мы просто случайным образом записываем повторяющиеся бессмысленные строки в content_c, и любая из них подойдет для использования в запросе»)

Caius Jard 28.05.2019 11:42

Нет, это не так. Речь идет о статьях и комментариях, и я хочу привести некоторую статистику. Вы можете увидеть это как content_c = статьи + комментарии & tab_s = тип статьи. Я хочу создать статистику: для каждого пользователя отображать количество комментариев, количество прокомментированных статей и «тип статьи». На самом деле, отображение количества комментариев работает, количество прокомментированных статей тоже, но когда я пытаюсь включить тип статьи (которая войдет в ORDER BY), это не сработало. Я постараюсь опубликовать некоторые данные.

P. Jerome 28.05.2019 11:44

Ваша таблица содержания содержит статьи и комментарии к ним? Эээ.. Мне будет интересно увидеть эту структуру данных, потому что кажется, что есть необходимость разделить те, которые уже

Caius Jard 28.05.2019 11:46

Нет, он содержит только идентификатор статей. Мне не нужно больше статей, поэтому я просто использую COUNT для id, чтобы получить количество статей.

P. Jerome 28.05.2019 11:55

У вас есть несколько записей в tab_s с одним и тем же shid и одним и тем же shid, также помеченным одним и тем же типом в столбце s.type .... и поэтому вы ищете LIMIT 1, верно?

mkRabbani 28.05.2019 12:16

Вот так. Но также обратите внимание, что у меня есть несколько записей в content_c с одним и тем же shid.

P. Jerome 28.05.2019 12:59
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
8
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Как обсуждалось в комментариях к вопросу, можете ли вы попробовать этот сценарий и посмотреть, соответствует ли он вашим требованиям? Это вернет строку для каждого идентификатора в таблице «content_c» с влиянием GROUP BY.

SELECT 
    cc.shid,
    cc.user,
    ts.type,
    sum(cc.qty1) + sum(cc.qty2) as qty_tot,
    COUNT(cc.id) as nb
FROM content_c cc
LEFT JOIN
(
    SELECT DISTINCT s.shid, s.type FROM tab_s s
) AS ts ON ts.shid = cc.shid
WHERE cc.time_i like '2019-01%'
GROUP BY cc.shid,cc.user,ts.type
Ответ принят как подходящий

Используйте коррелированный подзапрос:

SELECT cc.shid, cc.user, cc.type,
       SUM(cc.qty1) + SUM(cc.qty2) as qty_tot,
       COUNT(cc.id) as nb
FROM (SELECT cc.*,
             (SELECT s.type
              FROM tab_s s
              WHERE ts.shid = cc.shid
              LIMIT 1 
             ) as type
      FROM content_c cc
     ) cc
WHERE cc.time_i >= '2019-01-01' AND
      cc.time_i < '2019-02-01'
GROUP BY cc.shid, cc.user, cc.type;

Примечания:

  • Использование LIMIT без ORDER BY подозрительно. Почему в базовой таблице могут быть дубликаты?
  • Ваши сравнения дат плохи. Используйте функции даты/времени при работе со значениями даты/времени. Не используйте строковые функции.
  • GROUP BY должен включать все неагрегированные столбцы в SELECT.

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