#mysql
#mysql
Вопрос:
Я пытаюсь отобразить всех пользователей, которые находятся в определенном возрастном диапазоне (например, от 10 до 20), используя mysqli
. Какой запрос будет наилучшим для определения возраста и как?
В настоящее время у меня проблема с запросом, который не отображает точный результат. Я хочу отображать пользователей в возрасте от того-то и того-то, но приведенный ниже запрос не выдает никакой ошибки, а вместо этого отображает даже возраст ниже 10 или выше 20. У меня есть 2 таблицы user и user_likes.
user
username(pk) gender date_of_birth country
John M 2010-12-31 India
Bing M 2000-12-31 Italy
Rose F 2000-12-01 UK
user_likes
username(fk) gender age_from to_age
John F 18 30
Bing F 20 30
Rose M 18 25
$username
Ниже приведен сеанс, сохраненный в этой переменной.
$sql = "SELECT gender, age_from, to_age FROM user_likes WHERE username = '$username'";
$result = $conn->query($sql);
if ($result->num_rows > 0)
{
while ($row = $result->fetch_assoc())
{
$gender1 = $row['gender'];
$age_from = $row['age_from'];
$to_age = $row['to_age'];
}
}
$sql1 = "SELECT username, date_of_birth, TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) AS age FROM user WHERE NOT username = '$username' AND gender = '$gender1' AND (date_of_birth BETWEEN '$age_from' AND '$to_age')";
$result = $conn->query($sql1);
if ($result->num_rows > 0)
{
while ($row = $result->fetch_assoc())
{
echo "<div>";
echo "<span><a href = 'accounts.php?usernames=".$username."'><img src = '".$row['photo']."' alt = 'profile photo'></span>";
echo "<div>".$row['username']."</a><br><span>From".$row['country']."</span></div>";
echo "</div>";
}
}
Проблема в приведенном выше коде заключается в том, что если я выбираю возраст от 18 до 80, все равно отображается возраст ниже 18 или выше 80, поэтому я считаю, что это как-то связано с
TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) AS age
или
date_of_birth BETWEEN '$age_from' AND '$to_age'
Чего я ожидаю, так это того, что — предположим, я Роза, и поскольку мой пол интересов мужской, а выбранный возрастной диапазон от 18 до 25, я хочу, чтобы отображался только 'Bing'
пользователь.
Ответ №1:
date_of_birth BETWEEN '$age_from' AND '$to_age'
Давайте заменим поля некоторыми значениями.
'2010-12-31' BETWEEN '18' AND '20'
Это бессмысленно, возможно, вы захотите использовать
...
AND TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) BETWEEN '$age_from' AND '$to_age'
В примере :
Схема (MySQL версии 5.7)
CREATE TABLE users (
`username` VARCHAR(4),
`gender` VARCHAR(1),
`date_of_birth` VARCHAR(10),
`country` VARCHAR(5)
);
INSERT INTO users
(`username`, `gender`, `date_of_birth`, `country`)
VALUES
('John', 'M', '2010-12-31', 'India'),
('Bing', 'M', '2000-12-31', 'Italy'),
('Rose', 'F', '2000-12-01', 'UK');
Запрос # 1
SELECT username,
date_of_birth,
TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) AS "age"
FROM users
WHERE (TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) BETWEEN '18' AND '20');
Вывод
| username | date_of_birth | age |
| -------- | ------------- | --- |
| Bing | 2000-12-31 | 18 |
| Rose | 2000-12-01 | 18 |
Запрос # 2
SELECT username,
date_of_birth,
TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) AS "age"
FROM users
WHERE (TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) BETWEEN '01' AND '10');
Вывод
| username | date_of_birth | age |
| -------- | ------------- | --- |
| John | 2010-12-31 | 8 |
Комментарии:
1. замена date_of_birth на age ухудшает ситуацию, поскольку она вообще ничего не отображает, в то время как date_of_birth отображает всех пользователей, а не только требуемый возрастной диапазон
2. Правда, я допустил небольшую ошибку
3. Спасибо, это работает, но вы бы порекомендовали сделать это по-моему или предпочли бы другие методы?
4. У вас не так уж много выбора. Я буду использовать этот способ. Но я настоятельно рекомендую вам использовать параметризованные запросы, чтобы избежать SQL-инъекций
Ответ №2:
С моей точки зрения, в вашем запросе есть недостаток. В
...WHERE ... AND (date_of_birth BETWEEN '$age_from' AND '$to_age')
…вы сравниваете date_of_birth
(дату) с age
(целым числом). Это не имеет смысла, вы можете получить любой неожиданный результат.
Попробуйте изменить предложение WHERE, чтобы:
...WHERE ... AND (TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) BETWEEN '$age_from' AND '$to_age')
Заключительное предложение:
$sql1 = "SELECT username, date_of_birth, TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) AS age FROM user WHERE NOT username = '$username' AND gender = '$gender1' AND (TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) BETWEEN '$age_from' AND '$to_age')";
Комментарии:
1. Спасибо…. но я должен спросить — почему в моем запросе есть недостатки? а вы бы предпочли другие методы?
2. Отредактировано с ответом на ваш комментарий.