MySQL Query с некоторым типом соединения? Точно сказать не могу - PullRequest
1 голос
/ 01 сентября 2009

Если бы кто-нибудь мог порекомендовать хорошую книгу для изучения mySQL, это было бы здорово:).

У меня есть две таблицы, теги , codes_tags

CREATE TABLE `tags` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=190 DEFAULT CHARSET=utf8


CREATE TABLE `codes_tags` (
 `code_id` int(11) unsigned NOT NULL,
 `tag_id` int(11) unsigned NOT NULL,
 KEY `sourcecode_id` (`code_id`),
 KEY `tag_id` (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

То, что я пытаюсь сделать, это выбрать имя из «тегов» и количество этих tag_id в «codes_tags» и упорядочить их по этому количеству. Если в code_tags нет записей для этого tag_id, значение count должно быть равно 0 или NULL (предпочтительно 0).

Это самое близкое, к чему я дошел:

SELECT tags.name, COUNT( codes_tags.tag_id ) AS count
FROM tags
LEFT JOIN codes_tags ON tags.id = codes_tags.tag_id
GROUP BY tag_id
ORDER BY count DESC
LIMIT 0 , 30

Кажется, он делает то, что я хочу, однако он возвращает только четыре строки, когда должен возвращать 30.

Что я здесь не так делаю? Спасибо.

Ответы [ 3 ]

1 голос
/ 01 сентября 2009

Я проверил это на MySQL с некоторыми фиктивными данными, и запрос, кажется, возвращает мне более 4 строк. Я запустил ваши операторы создания таблиц, а затем заполнил их следующими утверждениями:

insert into tags (name) values ('java'), ('mysql'), ('php'), ('ruby'), ('.net'), ('python');
insert into codes_tags (code_id, tag_id) values (1,194), (2,194), (3,194), (1,191), (2,191), (3,191), (4,191), (5,191), (1,192), (1,195), (1,193);

Когда я запускаю ваш запрос по этим данным, он возвращает 6 строк. Для дальнейшей отладки вы можете опубликовать результаты следующих 2 запросов:

select count(*) from tags;
select * from tags limit 10;

Кроме того, чтобы убедиться, что вы обладаете надлежащей целостностью данных, можете ли вы добавить следующий внешний ключ и посмотреть, успешно ли он работает

alter table codes_tags add foreign key codes_tags_tag_id_key(tag_id) references tags(id);
0 голосов
/ 01 сентября 2009

Измените LEFT JOIN на LEFT OUTER JOIN

0 голосов
/ 01 сентября 2009

Я думаю, что если вы измените свой COUNT (codes_tags.tag_id) на COUNT (*) в SELECT, то также будут включены значения NULL. (Если значение равно нулю или 0 означает, что вы пропустили. В противном случае запрос выглядит нормально).

РЕДАКТИРОВАТЬ: После второй мысли, я пропустил левое соединение. Это означало бы, что вам нужны все теги, даже если они не связаны с чем-то в таблице code_tags. Это то, что вы хотите?

Я бы, наверное, сделал что-то вроде следующего:

SELECT tags.name, COUNT(*) AS count
FROM tags
INNER JOIN codes_tags ON tags.id = codes_tags.tag_id
GROUP BY tags.id
ORDER BY count(*) DESC

Это может быть выведено из элементов , а не в списке, теги которых также не включены в code_tags. Однако, если вы хотите явно сделать это также:

SELECT tags.name, COUNT(*) AS count
FROM tags
INNER JOIN codes_tags ON tags.id = codes_tags.tag_id
GROUP BY tags.id
UNION
SELECT tags.name, '0'
from tags
where tags.name not in 
   (SELECT tags.name
   FROM tags
   INNER JOIN codes_tags ON tags.id = codes_tags.tag_id)
ORDER BY count(*) DESC

(В данный момент у меня нет доступа к блоку SQL, так что принимайте запросы с недоверием; они не проверены.)

...