2015-04-04 3 views
1

В системе управления библиотекой, которую я разрабатываю, у меня есть таблица с деревом литературных жанров. Они кодируются как IP (код 2. стихи, код 2.1. Эпические стихи, код 2.1.2. Латинские эпические стихи и т. Д.).Нечетное поведение запроса JOIN

IP-код позволяет подсчитывать не только определенный жанр, но и всех его поджанров. Если я хочу знать, сколько стихов есть в библиотеке, все, что мне нужно сделать, это подсчитать коды 2.%.

Поскольку дерево будет заполнено в соответствии с потребностями библиотеки, когда они получат новые книги, есть поле с именем ord_vis, определяющее порядок визуализации строк (то есть новую строку об итальяно-турецкой войне 1911 года должны быть показаны до Первой мировой войны и Второй мировой войны, даже если они были вставлены после Шестидневной войны).

дерево работала гладко, пока я не решил посчитать количество заголовков с ниже запроса:

SELECT a.id, a.code, a.level, a.parent, a.text, 
     GROUP_CONCAT(b.text ORDER BY b.ord_vis SEPARATOR ', ') AS subs, 
     COUNT(books.id) AS total 
    FROM tree AS a 
    LEFT JOIN books ON books.code LIKE CONCAT(a.code, '%') 
    LEFT JOIN tree AS b ON b.parent = a.id 
     AND b.level = a.level +1 
    WHERE a.parent =42 -- this value is the user query 
    GROUP BY a.id 
    ORDER BY a.ord_vis ASC 

Как ни странно, если total> 0 или NOT NULL, то количество subs показано одно и то же из total: с 6 книгами и 3 поджанрами я получаю sub как «sub1, sub1, sub2, sub2, sub3, sub3».

Когда total равно 0, subs показаны в нужном количестве и порядке.

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

Я решил проблему, модифицирующую линию, получающую подводные лодки таким образом: GROUP_CONCAT(DISTINCT b.text ORDER BY b.ord_vis SEPARATOR ', ') AS subs, но я хочу понять, почему я получил эти нечетные результаты без DISTINCT.

Любой ключ?

+0

Вы можете сделать расчет в скрипте (я подозреваю, что LEFT не нужен?)? Например, php –

+0

В результате получается добавление DISTINCT в группу ... но я хочу понять, почему :-) –

+0

Чтобы узнать, почему DISTINCT влияет на вашу группировку (что не кажется странным вообще), мне нужно будет увидеть ваши данные. –

ответ

1

JOIN имеет тенденцию взорвать количество строк. DISTINCT - это способ воцариться во взрыве.

Другой подход (который иногда работает) является для нас коррелированным подзапросом. Это может (или не может) работать медленнее:

SELECT a.id, a.code, a.level, a.parent, a.text, 
     (SELECT GROUP_CONCAT(text ORDER BY ord_vis SEPARATOR ', ') 
      FROM tree 
      WHERE parent = a.id 
       AND level = a.level +1) AS subs, 
     COUNT(books.id) AS total 
    FROM tree AS a 
    LEFT JOIN books ON books.code LIKE CONCAT(a.code, '%') 
    WHERE a.parent =42 -- this value is the user query 
    GROUP BY a.id 
    ORDER BY a.ord_vis ASC 

+0

Что оставляет меня озадаченным, это нечетный образец результатов без DISTINCT. Я не думаю, что при поиске по 10 000 книг подзапрос будет иметь большое значение, но я попробую его на тестовой таблице с примерно 120 000 строк. Без левых жанры без книг не показаны. –

+0

Возможно, вы сможете почувствовать это, если вы сделаете SELECT без DISTINCT. Вы увидите практически повторяющиеся строки. Они будут отличаться только из-за одного из СОЕДИНЕНИЙ. Если вы также удалите этот JOIN, DISTINCT больше не понадобится. (Извините, я немного расплывчатый.) –

+0

Я вижу, что мне пришлось добавить DISTINCT даже в COUNT (книги.id), потому что я получил в общей сложности более 80 000 наименований на столе в 10 000 строк: своего рода схема Понци ... :-) –

Смежные вопросы