ВЫБЕРИТЕ список элементов и 5 тегов для каждого - PullRequest
1 голос
/ 11 марта 2010

Я пытаюсь запросить набор зданий, перечисленных в таблице, эти здания связаны с тегами. Я могу сделать это, но моя проблема в том, как ограничить количество тегов, чтобы увидеть:

table buildings
id    building_name     style
1     Pompidou          bla
2     Alcatraz          bla
3     etc.              etc.

table tags // they can be 50 or more per building
id    tag_name
1     minimal
2     gothic
3     classical
4     modern
5     etc.

table buildings_tags
id    building_id     tag_id

Я хотел сделать что-то подобное для получения списка, но это не так:

SELECT DISTINCT(tag), bulding_name
FROM buldings
INNER JOIN buildings_tags
ON buildings.id = buildings_tags.building_id
INNER JOIN tags
ON tags.id = buildings_tags.tag_id
LIMIT 0, 20

// result

building     tag
Pompidou     great
Pompidou     france
Pompidou     paris
Pompidou     industrial
Pompidou     renzo piano     <= How to stop at the 5th result?
Pompidou     hi-tech
Pompidou     famous place
Pompidou     wtf
etc..        etc...

этот запрос загружает здания, но этот запрос загружает все теги, связанные со зданием, а не только 5 из них?

Ответы [ 3 ]

2 голосов
/ 11 марта 2010

Мне кажется, что вы спрашиваете, отличается от того, что делает ваш запрос. Если я вас правильно понял, этот запрос должен делать то, что вам нужно:

SELECT bulding_name, tag
FROM   buldings b
  LEFT JOIN (SELECT tag, building_id
              FROM   tags
                INNER JOIN buildings_tags
                  ON tags.id = buildings_tags.tag_id
              WHERE  building_id = b.id
              LIMIT  5) t
    ON b.id = t.building_id
ORDER BY bulding_name

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

0 голосов
/ 12 марта 2010
SELECT a.building_name, a.tag_name
FROM (
 SELECT b.building_name, t.tag_name, bt.building_id
 FROM tags t
  INNER JOIN buildings_tags bt ON (bt.tag_id=t.id)
  INNER JOIN buildings b ON (b.id=bt.building_id)
 ORDER BY bt.building_id
) a
,
(SELECT @prev:=-1, @count:=1) b
WHERE
 CASE WHEN @prev<>a.building_id THEN
   CASE WHEN @prev:=a.building_id THEN
    @count:=1
   END
 ELSE
   @count:=@count+1
 END <= 5

Если это соответствует вашим потребностям, то объяснение примерно того же запроса здесь

0 голосов
/ 11 марта 2010

Если я понимаю вашу идею, вы должны изменить:

LIMIT 0,20

по:

LIMIT 0,5

или просто:

LIMIT 5

Вот и все!

...