#php #pdo #left-join
#php #pdo #левое соединение
Вопрос:
У меня есть две таблицы:
-
Пользователи
Стандартная таблица пользователей (идентификатор, имя, адрес электронной почты, страна, город, пароль, пол).
-
языки
Каждый столбец имеет название языка, например, «английский», «испанский», «русский». Значением любого столбца является значение int, которое указывает уровень владения соответствующим языком.
Идентификатор для каждой строки извлекается из таблицы user user.id
, чтобы сохранить языки пользователя. стандартная запись является NULL
и будет заменена на int, если пользователь говорит на языке.
Я хочу выбрать всех пользователей, которые соответствуют вводу поискового запроса (страна, город, пол), затем я хочу проверить языковую таблицу по идентификатору пользователя, взятому из таблицы пользователей LEFT JOIN languages ON (user.id=languages.id)
, и получить обратно только имя столбца и значения столбцов, которые не содержат NULL
.
Мой подход до сих пор:
sql = 'SELECT * FROM ' . self::TABLE .
' WHERE country=? AND city LIKE ? AND gender LIKE ? LEFT JOIN languages ON ('.
self::TABLE .
'.id=languages.id) SHOW COLUMNS WHERE COLUMN NAME ? ORDER BY name DESC';
Приведенный выше код явно ошибочен, мой вопрос в том, как мне поступить с этим после ПОКАЗА СТОЛБЦОВ?
Примеры записей: языковая таблица user_id = 9, английский = NULL, испанский = 3, русский = 2, корейский = 1
идентификатор таблицы пользователя = 9, адрес электронной почты = me@me.com , страна = Южная Корея, город = Сеул, пол = 1
После того, как я выберу только пользователей, которые соответствуют стране, городу и полу, указанным в поисковом запросе, я хочу взять идентификатор каждого пользователя и проверить языковую таблицу на наличие столбцов, содержащих значение not null, и добавить эти имена столбцов вместе с их значением в объект user для каждого пользователя отдельно, затем вернуть всеобъекты, поэтому я могу выводить их зарегистрированному пользователю, который выполняет поиск.
Как я ВСТАВЛЯЮ и ОБНОВЛЯЮ языки:
public function updateLanguages($languages, $id) {
$sql = "SELECT user_id FROM " . self::TABLE . " WHERE user_id=? LIMIT 1";
$stmt = $this->dbh->prepare($sql);
$stmt->execute(array($id));
$userId = $stmt->fetchAll();
if (empty($userId)) {
$sql = 'INSERT INTO ' . self::TABLE . ' (user_id) VALUES(?)';
$values = array($id);
$stmt = $this->dbh->prepare($sql);
$stmt->execute($values);
$this->resetLanguages($id);
for ($i = 0; $i < count($languages) / 2; $i ) {
$sql = 'UPDATE ' . self::TABLE . ' SET ' . $languages['language' . $i] . '=? WHERE user_id =? LIMIT 1';
$stmt = $this->dbh->prepare($sql);
$stmt->execute(array($languages['langlevel' . $i], $id));
$stmt = null;
}
} else {
$this->resetLanguages($id);
for ($i = 0; $i < count($languages) / 2; $i ) {
$sql = 'UPDATE ' . self::TABLE . ' SET ' . $languages['language' . $i] . '=? WHERE user_id =? LIMIT 1';
$stmt = $this->dbh->prepare($sql);
$stmt->execute(array($languages['langlevel' . $i], $id));
$stmt = null;
}
}
}
Функция сброса:
public function resetLanguages($id) {
$languages = new Languages();
$allLangs = $this->getLanguages();
$allLangs = array_slice($allLangs, 1, 137);
foreach ($allLangs as $lang) {
$sql = 'UPDATE ' . self::TABLE . ' SET ' . $lang['Field'] . '=? WHERE user_id =? LIMIT 1';
$stmt = $this->dbh->prepare($sql);
$stmt->execute(array(null, $id));
$stmt = null;
}
}
Вставка пользователя:
public function save($data) {
$utilityManager = new UtilityManager();
$rand = $utilityManager->randomGen();
$user = new User();
$user->arrayToObject($data);
$folderName = $user->getName() . $rand;
$profileFolder = 'profilePic';
mkdir('users/' . $folderName, 0755);
mkdir("users/$folderName/" . $profileFolder, 0755);
$sql = 'INSERT INTO ' . self::TABLE . ' (name, email, country, password, emailConfirm, imageFolder, registered, lastOnline) VALUES(?, ?, ?, ?, ?, ?, NOW(), NOW())';
$values = array($user->getName(), $user->getEmail(), $user->getCountry(), $user->getPassword(), $user->getEmailConfirm(), $folderName);
$stmt = $this->dbh->prepare($sql); // prepares the sql statement to be filled
$stmt->execute($values); //fills the sql statement with the $values array
if ($stmt->rowCount() > 0) {
$utilityManager->sendEmail(array('reg', $user->getEmail(), $user->getName(), $user->getEmailConfirm()));
}
}
Комментарии:
1. можете ли вы привести примеры записей и ожидаемые результаты?
2. Вы не можете получить имя столбца SQL. Но вы можете сделать обходной путь, установив для столбца comnent то же значение, что и имя столбца, и вместо этого получить его в своем запросе
3. ваш дизайн базы данных неверен. таблица языков должна содержать только два столбца: user_id и language_id. в этом случае запрос будет проще простого.
4. @JohnWoo я добавил примеры записей для обеих таблиц.
5. Я не могу понять ваш вопрос, кажется, в нем много ошибок в лекциях, или я не могу этого сделать. В любом случае, пожалуйста, четко опишите вашу проблему, используя пример.
Ответ №1:
Ваш дизайн базы данных неверен. таблица языков должна содержать только два столбца: user_id и language_id
В этом случае вы можете просто объединить таблицу users с таблицей language
SELECT * FROM users u, languages l
WHERE u.id = user_id AND lang_id=? AND country=? AND city LIKE ? AND gender LIKE ?
Обратите внимание, что при правильной структуре вы получите много преимуществ. Например, вместо того, чтобы указывать только «да» или «нет» для языка, вы можете добавить поле «уровень владения», чтобы отметить разные градации. А затем выберите всех пользователей, чей уровень владения выбранным языком не ниже заданного.