2012-04-04 2 views
2

по какой-либо причине нижеприведенный запрос позволяет дублировать имена. Почему это?SQL-запрос не группируется должным образом

SELECT id, name_without_variants, SUM(relevance) as total_relevance FROM (
    SELECT 
     card_definitions.id, 
      card_definitions.name_without_variants, 
     (MATCH(card_definitions.name_without_variants) AGAINST ('lost soul site discard')) * 0.40 AS relevance 
     FROM card_definitions 
     GROUP BY name_without_variants, id 
    UNION 
    SELECT 
     card_definitions.id, 
      card_definitions.name_without_variants, 
     (MATCH(card_def_identities.special_ability_text) AGAINST ('lost soul site discard')) * 0.05 AS relevance 
     FROM card_def_identities 
     INNER JOIN card_definitions ON card_def_identities.card_def_sid = card_definitions.id 
     GROUP BY name_without_variants, id 
    UNION 
    SELECT 
     card_definitions.id, 
      card_definitions.name_without_variants, 
     (MATCH(brigades.brigade_color) AGAINST ('lost soul site discard')) * 0.30 AS relevance 
     FROM brigades 
     INNER JOIN card_def_brigades ON brigades.id = card_def_brigades.brigade_sid 
     INNER JOIN card_definitions ON card_def_brigades.card_def_sid = card_definitions.id 
     GROUP BY name_without_variants, id 
    UNION 
    SELECT 
     card_definitions.id, 
      card_definitions.name_without_variants, 
     (MATCH(identifiers.identifier) AGAINST ('lost soul site discard')) * 0.20 AS relevance 
     FROM identifiers 
     INNER JOIN card_def_identifiers ON identifiers.id = card_def_identifiers.identifier_sid 
     INNER JOIN card_definitions on card_def_identifiers.card_def_sid = card_definitions.id 
     GROUP BY name_without_variants, id 
    UNION 
    SELECT 
     card_definitions.id, 
      card_definitions.name_without_variants, 
     (MATCH(card_effects.effect) AGAINST ('lost soul site discard')) * 0.05 AS relevance 
     FROM card_effects 
     INNER JOIN card_def_effects ON card_effects.id = card_def_effects.effect_sid 
     INNER JOIN card_definitions on card_def_effects.card_def_sid = card_definitions.id 
     GROUP BY name_without_variants, id 
    ) AS combined_search 
GROUP BY name_without_variants, id 
HAVING total_relevance > 0 
ORDER BY total_relevance DESC 
LIMIT 10; 

Вот результат, который я получаю. Обратите внимание на два Lost Soul [Site Doubler]

2623 Lost Soul [Deck Discard] 6.35151714086533 
1410 Lost Soul [Hand Discard] 6.29273346662521 
1495 Lost Soul [Discard Card] 5.93360201716423 
1442 Lost Soul [Demon Discard] 5.91308708190918 
1497 Lost Soul [Site Doubler] 5.05888686180115 
1498 Lost Soul [Site Doubler] 5.05888686180115 
2572 Lost Soul [Site Guard] 4.82421946525574 
2774 Lost Soul [Far Country] 3.39325473308563 
2891 Fortify Site [RoA2] 2.77084048986435 
1418 Lost Soul [Hopper] 2.63041100502014 

ответ

2

Поскольку идентификаторы различны, и вы группирование по ID, вы получите несколько строк для каждого, это то, что делает GROUP BY. Если вы измените верхний уровень SELECT к

SELECT name_without_variants, SUM(relevance) as total_relevance 

и внешний GROUP BY для:

GROUP BY name_without_variants 

вы должны увидеть различные имена, но больше не будет иметь идентификатор.

+0

Вы также должны добавить агрегатную функцию в столбец идентификаторов, если вы удалите его из группы заявления. Вам понадобится min/max или что-то подобное. –

0
GROUP BY name_without_variants, id 

Вы группируете имя_without_variants, id. Идентификационные данные различаются по двум записям:

1497 Lost Soul [Site Doubler] 5.05888686180115 
1498 Lost Soul [Site Doubler] 5.05888686180115 

Вам необходимо решить, как вы будете управлять идентификатором.

Удалите идентификатор из группы и добавьте функцию агрегата в столбец id в выбранном вами элементе. Или просто удалите столбец все вместе.

Вот пример, который был сведен к одному запросу. Пожалуйста, поймите, что у меня нет полной перспективы на вашу схему или данные, и это не было протестировано. Я также делаю некоторые предположения здесь. Однако, если схема относительна, это должно вернуть то, что вы ищете:

SELECT cd.id, cd.name_without_variants, (((MATCH(cd.name_without_variants) AGAINST ('lost soul site discard')) * 0.40)+ 
            ((MATCH(cdi.special_ability_text) AGAINST ('lost soul site discard')) * 0.05)+ 
            ((MATCH(b.brigade_color) AGAINST ('lost soul site discard')) * 0.30)+ 
            ((MATCH(i.identifier) AGAINST ('lost soul site discard')) * 0.20)+ 
            ((MATCH(ce.effect) AGAINST ('lost soul site discard')) * 0.05) 
           ) as total_relevance 
FROM card_definitions cd 
LEFT OUTER JOIN card_def_identities cdi ON cd.id=cdi.card_def_sid 
LEFT OUTER JOIN brigades b ON cd.id=b.card_def_sid 
LEFT OUTER JOIN identifiers i ON i.id=cdi.identifier_sid 
LEFT OUTER JOIN card_def_effects cde ON cde.card_def_sid=cd.id 
LEFT OUTER JOIN card_effects ce ON ce.id=cde.effect_sid 
GROUP BY cd.id, cd.name_without_variants 
HAVING total_relevance > 0 
ORDER BY total_relevance DESC 
LIMIT 10; 
+0

О, я думал, что группа будет группировать имя, а затем, если бы были какие-то дубликаты, группируйте их по id. Мне все еще нужен идентификатор. Как я могу получить только 1 на идентификаторы и убедиться, что нет дубликатов имен? – LordZardeck

+0

Вы должны использовать min/max в столбце id. Тем не менее, тогда вы получите произвольный идентификатор из одного из утвержденных операторов select. Было бы разумно просто удалить идентификатор из верхнего уровня, так как он не будет иметь большого значения. В противном случае вам нужно будет добавить статический столбец в свои команды выбора union, чтобы вы знали, из какого выражения пришел идентификатор. Имеют смысл? Я могу отредактировать ответ, чтобы показать, если это необходимо. –

+0

Мне нужен идентификатор. Это единственное, что я на самом деле использую. Если бы вы не возражали, я мог бы увидеть пример? Я ничего не знаю о min/max – LordZardeck

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