Многократный левый предел соединения MySQL - PullRequest
0 голосов
/ 05 мая 2018

Как наложить ограничение на левое соединение для запроса с несколькими левыми объединениями, которые зависят друг от друга? См. Комментарий ниже по ПРЕДЕЛУ:

SELECT 
    a.*,GROUP_CONCAT(c.body SEPARATOR ' ') AS bodies
FROM a   
    LEFT JOIN b ON b.id_a=a.id    
    LEFT JOIN c ON c.id=b.id_c LIMIT 5 # LIMIT 5 Here Does Not Work 
WHERE ...

Пример набора данных ...

DROP TABLE IF EXISTS `a`;
CREATE TABLE `a` (  
  `id` int(11) NOT NULL
);

-- Contains relationship between a and c
DROP TABLE IF EXISTS `b`;
CREATE TABLE `b` (
  `id_a` int(11) NOT NULL,
  `id_c` int(11) NOT NULL
);

-- Contains body contents
DROP TABLE IF EXISTS `c`;
CREATE TABLE `c` (
  `id` int(11) NOT NULL,
  `body` varchar(2000) NOT NULL
);


-- ----------------------------
-- Sample Records
-- ----------------------------
INSERT INTO `a` VALUES ('1');

INSERT INTO `b` VALUES 
('1','1'), ('1','2'), ('1','3'),
('1','4'), ('1','5'), ('1','6'),
('1','7'), ('1','8'), ('1','9'), 
('1','10');

INSERT INTO `c` VALUES
('1','aa'),('2','bb'), ('3','cc'),
('4','dd'), ('5','ee'), ('6','ff'),
('7','gg'), ('8','hh'), ('9','ii'),
('10','jj');

... и SQLFiddle на http://sqlfiddle.com/#!9/c1822/12

Также здесь есть перезапись подзапроса, которую я пробовал, но она не работает, потому что внешняя таблица не доступна из вложенного подзапроса и завершается с «неизвестным столбцом a.id в предложении where»: http://sqlfiddle.com/#!9/c1822/3

Также здесь есть подзапрос find_in_set rewrite http://sqlfiddle.com/#!9/2d43bb/1, который работает, но слишком медленно с большими наборами данных.

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

Вот правильный способ написать это, используя переменные. Решение Andomar может работать, но оно страдает тремя проблемами:

  • В более поздних версиях MySQL order by должен находиться в подзапросе.
  • Что еще более важно, MySQL не гарантирует порядок вычисления выражений в select. Поэтому вам не следует присваивать переменную в одном выражении и использовать ее в другом.
  • Переменные не инициализируются в запросе

Итак, лучшая версия выглядит так:

select . . .
from table1 t1 left join
     (select t2.*,
             (@rn := if(@id = t2.t1_id, @rn + 1,
                        if(@id := t2.t1_id, 1, 1)
                       )
             ) as rn
      from (select t2.*
            table2 t2
            order by t1_id
           ) t2 cross join
           (select @rn := 0, @id := -1) params
     ) t2
     on t2.t1_id = t1.id
where t2.rn <= 5;  -- At most 5 rows

Использование group_concat() предполагает, что group by также необходим. Однако ваш вопрос кажется более общим об ограничении строк, и вы не предоставляете много информации о том, что вы на самом деле пытаетесь достичь.

0 голосов
/ 05 мая 2018

Вы можете использовать переменные для нумерации каждой строки в подзапросе. Затем вы можете отфильтровать строки на основе этого числа. Этот пример ограничивает left join максимум 3 результатами с одинаковыми t1_id:

select  *
from    table1 t1
left join
        (
        select  @rn := case when t1_id = @prev_id then @rn + 1 else 1 end rn
        ,       @prev_id := t1_id
        ,       t2.*
        from    table2 t2
        order by
                t1_id
        ) t2rn
on      t2rn.t1_id = t1.id
        and t2rn.rn < 4  -- At most 3 rows

Пример на скрипте SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...