Проблема с таблицей JOIN в MySQL и агрегацией - PullRequest
1 голос
/ 13 декабря 2008

У меня есть три таблицы. Этот запрос записывает правильный ответ (x-строки для btv.id_user с соответствующими btv.cas и race.id_zavod

SELECT `btv.id_user`, `btv.id_zavod`,`btv.cas`
FROM `btv`
JOIN `btu` ON `btv.id_user` = `btu.id_user`
JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
WHERE `race.type` = '8' AND `btv.id_user` = '607'

Результат:

| 607 |  512 | 03:15:58 |  
| 607 |  730 | 03:01:18 |  
| 607 |  164 | 03:07:26 |  
| 607 |  767 | 02:58:31 |  
| 607 | 1147 | 03:06:47 |  
| 607 | 1149 | 03:09:41 |  
| 607 | 1178 | 03:24:20 | 

Но когда я пытаюсь агрегировать его в один ряд с помощью id_user, он возвращает правильный min btv.cas, но неверное соединение неправильно

SELECT `btv.id_user`, `btv.id_zavod`, MIN( `btv.cas` )
FROM `btv`
JOIN `btu` ON `btv.id_user` = `btu.id_user`
JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
WHERE `race.type` = '8' AND `btv.id_user` = '607'
GROUP BY `btv.id_user`

Результат:

| 607 | 512 | 02:58:31 |

Ответы [ 5 ]

1 голос
/ 13 декабря 2008

Вы написали запрос:

SELECT `btv.id_user`, `btv.id_zavod`, MIN( `btv.cas` )
FROM `btv`
JOIN `btu` ON `btv.id_user` = `btu.id_user`
JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
WHERE `race.type` = '8' AND `btv.id_user` = '607'
GROUP BY `btv.id_user`

не будет работать. Вам нужна группа по id_zavod или что-то. Можете ли вы сказать нам, какой запрос вы действительно выполняете? И какой результат вы ожидаете?

0 голосов
/ 13 декабря 2008

Вы просто пытаетесь получить самое низкое значение btv.cas и другие соответствующие ему столбцы? Если это так, вы можете просто заказать по btv.cas и ограничить 1 хит:

SELECT `btv.id_user`, `btv.id_zavod`,`btv.cas`
FROM `btv`
JOIN `btu` ON `btv.id_user` = `btu.id_user`
JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
WHERE `race.type` = '8' AND `btv.id_user` = '607'
ORDER BY `btv.cas` LIMIT 1
0 голосов
/ 13 декабря 2008

Я не уверен, что вы пытаетесь достичь, но вы, возможно, ищете функцию GROUP_CONCAT? ?

0 голосов
/ 13 декабря 2008

Когда вы используете GROUP BY, столбцы в списке выбора должны удовлетворять одному из следующих:

  • Столбец назван в GROUP BY (например, btv.id_user в вашем примере)
  • Столбец находится внутри статистической функции (например, MIN( btv.cas ))
  • Столбец - это функциональная зависимость столбцов, которые вы назвали в GROUP BY.

Это ошибка в вашем запросе: btv.id_zavod имеет много значений для каждого значения btv.id_user. Это не удовлетворяет функциональной зависимости. В id_zavod должно быть только одно значение для каждого значения id_user, чтобы оно было функциональной зависимостью.

В некоторых брендах баз данных этот запрос фактически выдает ошибку. MySQL более гибок, доверяя вам имена только столбцов в списке выбора, которые являются функциональными зависимостями столбцов, которые вы назвали в GROUP BY.

Вот запрос, который возвращает то, что вы хотите, значение MIN btv.cas на id_user с соответствующим значением btv.id_zavod:

SELECT b1.id_user, b1.id_zavod, b1.cas
FROM btv AS b1
 JOIN btu ON (b1.id_user = btu.id_user)
 JOIN race ON (b1.id_zavod = race.id_zavod)
 LEFT OUTER JOIN btv AS b2 ON (b1.id_user = bt2.id_user AND 
   (b1.cas > b2.cas OR (b1.cas = b2.cas AND b1.primarykey > b2.primarykey))
WHERE race.type = '8' AND b1.id_user = '607'
 AND b2.id_user IS NULL;

Другими словами, вам нужно выполнить соединение, как и раньше, но затем снова присоединить его к btv, чтобы увидеть, есть ли еще строка с таким же значением id_user и меньшим значением в cas. Используйте OUTER JOIN, потому что вы ищете случай, когда нет совпадения. Вы можете проверить это с помощью b2.id_user IS NULL, потому что OUTER JOIN делает все столбцы NULL, когда нет совпадений.

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

Вам не нужно использовать GROUP BY в этом запросе. Об этом позаботились неявно, потому что будет только одна строка, которая удовлетворяет условию OUTER JOIN.

0 голосов
/ 13 декабря 2008

Попробуйте:

SELECT `btv.id_user`, `btv.id_zavod`, MIN( `btv.cas` )
FROM `btv`
Inner JOIN `btu` ON `btv.id_user` = `btu.id_user`
Inner JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
WHERE `btv.id_user` = '607'
GROUP BY `btv.id_user` having `race.type` = '8'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...