Не удалось связать составной идентификатор [37000] — запрос SQL 2005

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

Во всяком случае, у меня есть приложение на основе PHP на форуме, которое позволяет пользователям давать очки репутации друг другу, я уверен, что вы все знаете, как работают эти простые настройки, поэтому я не буду останавливаться на этом. Проблема в том, что этот фрагмент кода изначально был написан для MySQL, и хотя 95% его было преобразовано и теперь работает в MS SQL, остаются некоторые запросы, которые, как я подозреваю, не работают в SQL 2005. из-за небольших синтаксических несоответствий в соединениях и т. д. Это меня застряло. Пример запроса выглядит следующим образом:

SELECT TOP 25 p.post_id, p.post_subject, p.forum_id, u.username, u.user_id, 
 u.user_colour, r.rep_id, r.rep_from, r.rep_to, r.rep_time, r.rep_post_id, 
 r.rep_point, r.rep_comment, r.enable_urls, r.rep_ip_address, r.username 
FROM forum_reputations r, forum_users u 
LEFT JOIN forum_posts p ON (r.rep_post_id = p.post_id) 
WHERE r.rep_to = 61
ORDER BY r.rep_id DESC

Данные следующие:

**Forum_Posts**:
post_id (int, PK)
post_subject (varchar)
forum_id (int)

**Forum_users**:
username (varchar)
user_id (int, PK)
user_colour (varchar)

**Forum_reputations**:
rep_id (int, PK)
rep_from (int) 
rep_to (int)
rep_time (int)
rep_post_id (int)
rep_point (int)
rep_comment (text)
enable_urls (int) 
rep_ip_address (varchar) 
username (varchar)

Когда запрос выполняется, SQL Server выдает следующую знакомую ошибку:

[Microsoft][ODBC SQL Server Driver][SQL Server]The multi-part identifier "r.rep_post_id" could not be bound. [37000]

Я изо всех сил пытаюсь понять, почему это происходит. Это явно намекает на то, что rep_post_id имеет проблему, но я проверил синтаксис запроса и имена столбцов/таблиц, и все они верны, я даже попытался заключить любые объекты, которые отдаленно звучат как зарезервированные слова SQL, в квадратные скобки (т.е. u.[имя пользователя ], r.[имя пользователя] и т. д.), но это не имеет значения. Интересно, что если я изменю предложение FROM так, чтобы Forum_users u стоял перед Forum_users r, ошибка больше не возникает, и данные возвращаются, но это не очень полезно, потому что это разрушает левое соединение и извлекает 25 лучших из таблицы пользователей, игнорируя наличие связанных записей в таблице репутаций.

Предполагается, что вывод должен состоять из таблицы, в которой для каждой записи представителя пользователя (r.rep_to) перечислено следующее:

Количество полученных очков повторения (r.rep_point)

Пользователь, поставивший баллы (r.rep_from, u.user_id, u.username)

Дата начисления баллов (r.rep_time)

Комментарий, введенный пользователем, дает количество очков репутации (r.rep_comment)

Сообщение на форуме, что репутация была дана для (r.rep_post_id, p.post_id, p.post_subject)

Если у кого-то есть какие-либо мысли о том, где что-то идет не так или как это можно реструктурировать, я был бы очень признателен, если бы услышал об этом. Я понимаю, что это, вероятно, что-то очень рудиментарное, но я действительно не вижу здесь леса за деревьями!

Спасибо


person Ciarán Reilly    schedule 09.11.2011    source источник
comment
FROM forum_reputations r, forum_users u даст вам декартово соединение.   -  person Martin Smith    schedule 09.11.2011
comment
Спасибо за этот полезный указатель, в настоящее время я более подробно изучаю ситуации с декартовым соединением, кажется, какой-то другой код, к которому я еще не добрался, эта проблема также просто смотрит на нее, возможно, вы спасли меня от будущей головы царапать! :)   -  person Ciarán Reilly    schedule 09.11.2011


Ответы (2)


пытаться

SELECT TOP 25 p.post_id, p.post_subject, p.forum_id, u.username, u.user_id, 
 u.user_colour, r.rep_id, r.rep_from, r.rep_to, r.rep_time, r.rep_post_id, 
 r.rep_point, r.rep_comment, r.enable_urls, r.rep_ip_address, r.username 
FROM forum_reputations r
JOIN forum_users u 
ON u.user_id = r.rep_from
LEFT JOIN forum_posts p ON r.rep_post_id = p.post_id 
WHERE r.rep_to = 61
ORDER BY r.rep_id DESC

Это не имеет прямого отношения к вашему вопросу, но в вашем запросе отсутствует условие соединения между forum_users и forum_reputation - это будет производить декартово произведение. Я добавил соединение выше, но немного догадываюсь, находится ли оно в правом столбце.

person Ed Harper    schedule 09.11.2011
comment
Это действительно правильно по деньгам! И вам удалось правильно указать имя столбца, насколько я вижу, его возвращаемые данные, правильное соединение и теперь без ошибок. Большое спасибо за это, очень признателен :) Мне придется освежить свои соединения, я не осознавал, что стандартное плоское СОЕДИНЕНИЕ может применяться вне LEFT и все равно считаться так. Cпасибо за помощь :) - person Ciarán Reilly; 09.11.2011

Вы не можете комбинировать неявные и явные соединения и ожидать, что это будет работать правильно. Вы должны сделать все соединения явными, что вы должны делать в любом случае, поскольку неявные соединения являются антипаттерном SQL.

Это версия явного присоединения к тому, что у вас есть:

SELECT TOP 25 p.post_id, p.post_subject, p.forum_id, u.username, u.user_id,
u.user_colour, r.rep_id, r.rep_from, r.rep_to, r.rep_time, r.rep_post_id,  
r.rep_point, r.rep_comment, r.enable_urls, r.rep_ip_address, r.username  
FROM forum_reputations r
CROSS JOIN forum_users u  
LEFT JOIN forum_posts p ON r.rep_post_id = p.post_id  
WHERE r.rep_to = 61 
ORDER BY r.rep_id DESC 

Однако я подозреваю, что это НЕ то, что вы хотите. Я думаю, что у @EdHarper правильная идея.

person HLGEM    schedule 09.11.2011
comment
Привет, вы совершенно правы, запрос Эда сработал, но я пока не видел вашего поста. Я также собираюсь попробовать ваш запрос с соединением CROSS, чтобы лучше понять внутренние различия между ними, спасибо за ваш вклад и помощь в дальнейшем улучшении понимания JOINS. - person Ciarán Reilly; 09.11.2011