Это меня беспокоит, я не могу понять это. Я воспользуюсь аналогией с продуктами питания, чтобы попытаться упростить мою задачу.
1000 представителей общественности попросили выбрать по каждой из 13 категорий обуви для ног. Эти выборы затем сохранялись в базе данных mysql под своим именем.
e.g. billy mary etc. etc.
milk....semi. .skimmed...
bread...white...brown....
cheese..edam.....edam....
fruit...apple...orange...
veg....potato...sprout...
meat....beef.....beef....
sweet..bonbons..liquorice..
fish...trout....salmon...
crisp....s&v....plain....
biscuit..hovis..rich tea..
wine.....red.....red.....
beer....stella..carlsburg..
carb....coke.....pepsi....
Затем одного из этих 1000 попросили выбрать от нуля до 13 вариантов с помощью флажков.
Путем поиска в базе данных, сколько других выбрали те же сорта?
Отобразите в таблице все их названия и то, что они выбрали для всех 13 разновидностей.
Имеет ли это смысл? Я надеюсь на это, потому что это сводит меня с ума.
Привет, Халлгрим. Конечно. Таблица содержит названия продуктов и участников в виде текстовых полей. То, что они выбрали из каждого поля, записывается напротив их имен. Их имена уникальны и увеличиваются с помощью идентификатора пользователя. Есть только одна таблица.
Значит, в таблице 13 столбцов с продуктами питания?
Привет, Дэррил. Да и одно имя и один идентификатор пользователя.
Я думаю, было бы намного проще иметь 2 таблицы, одну с пользователем, а другую с отношениями между продуктами и идентификатором user_id.
о, я не знаю - если это очень простая информация, подобная этой, с очень ограниченным объемом данных, то использование более одной таблицы, вероятно, будет излишним.






частичный ответ:
поэтому сначала вы должны выполнить расчет, буквально поместив строки в какое-нибудь поле, например «молоко | полу | обезжиренное».
Предполагая, что у вас простой макет, у вас будет что-то вроде этого (я ограничусь тремя категориями):
PersonId What_Milk What_Bread What_Cheese
1 Semi Wheat Swiss
2 Skimmed Rolls French
3 Soy Brown Smelly
4 Low Fat Wheat Swiss
Если я правильно понял, ваша проблема в следующем:
Когда человека 4 просят выбрать 0 .. 3 из его продуктов питания, он может установить флажки «Хлеб» и «Сыр», что означает, что запрос должен дать человека 1 в качестве совпадения. Верно?
SELECT
PersonId,
What_Milk,
What_Bread,
What_Cheese
FROM
FoodPreference
WHERE
PersonId != ?
AND What_Milk = IFNULL(NULLIF(?, ''), What_Milk)
AND What_Bread = IFNULL(NULLIF(?, ''), What_Bread)
AND What_Cheese = IFNULL(NULLIF(?, ''), What_Cheese)
Значения вашего флажка позже переместятся туда, где находятся заполнители вопросительного знака. (Я заменил конструкции CASE WHEN, которые использовались здесь, на IFNULL / NULLIF, которые имеют тот же эффект, но более удобны для подготовленных операторов PHP.)
Если флажок не установлен (таким образом, фиксируя значение чего-либо), соответствующий столбец сравнивается с самим собой. Это означает, что его значение не влияет на результат. Если другие столбцы совпадают, будет выбрана строка.
Это также означает, что если пользователем установлены флажки нуль, будут возвращены строки все. Чем больше продуктов выберет человек, тем точнее совпадение будет.
В PHP я бы рекомендовал вам использовать mysqli_prepare() для создания подготовленного оператора из строки запроса и mysqli_stmt_bind_param() для привязки фактических значений к заполнителям вопросительного знака. Это намного безопаснее, чем строить строку SQL напрямую. В документации PHP есть много информации о mysqli., взгляните на него.
Привет Томалак. Да, если человеку 4 в вашем примере было предложено выбрать, и он установил флажки «Хлеб» и «Сыр», тогда все, кто выбрал то же, что и она, для этих двух продуктов питания должны быть отклонены. Поскольку нам нужно отображать все, что они выбрали, SELECT должен быть * not PersonId? И да, чем меньше .....
..... флажки отмечены тем больше результатов. Установка флажков сужает поиск. Я не знаю этого СЛУЧАЯ КОГДА термин? Сейчас поищу.
Да, выберите те столбцы, которые вам нужны, это был пример. Избегайте общего «SELECT *» в производственном коде, он менее эффективен.
Я поддерживаю предложение Томалака использовать подготовленные параметры оператора вместо интерполяции переменных PHP в выражения SQL.
В ПОРЯДКЕ. Итак, если значение флажка идет туда, где у вас есть? что делают пустые кавычки?
Пустые кавычки - это небольшая хитрость, заставляющая NULLIF производить NULL, если вы не указываете значение флажка, поэтому IFNULL может заменить его исходным значением столбца. Прочтите также документацию по mysql и попробуйте сами выражения, чтобы понять их.
SELECT
PersonId,
milk,
bread,
cheese
FROM FoodPreference
WHERE PersonId != :chosen_person_id
AND $milk= CASE WHEN :isset($_POST["milk"]))> '' THEN :isset($_POST["milk"])) ELSE milk END
AND $bread= CASE WHEN :isset($_POST["bread"]))> '' THEN :isset($_POST["bread"])) ELSE bread END
AND $cheese= CASE WHEN :isset($_POST["cheese"]))> '' THEN :isset($_POST["cheese"])) ELSE cheese END
Я на правильном пути?
Попробуйте использовать кнопку формата кода, чтобы сделать отступ в коде и сделать его более читабельным. Я думаю, вы приближаетесь ... как-то. Я немного обновлю свой пример, поскольку знаю, что вы используете PHP.
Хорошо, я отправил один ответ, но Томалак совершенно справедливо указал на логический недостаток. Попробую еще раз:
Альтернативой перечислению категорий в виде тринадцати столбцов является перечисление их в виде тринадцати строк в таблице, как показано ниже:
CREATE TABLE FoodPreference (
PersonID INT NOT NULL REFERENCES People,
FoodCat VARCHAR(10) NOT NULL REFERENCES FoodCategories,
FoodChoice VARCHAR(10) NOT NULL,
PRIMARY KEY (PersonID, FoodCat)
);
INSERT INTO FoodPreference VALUES
(123, 'bread', 'white'),
(123, 'milk', 'skim'),
(123, 'cheese', 'edam'), ...
(321, 'bread', 'brown'),
(321, 'milk', 'whole'),
(321, 'cheese', 'edam'), ...
Затем вы можете использовать следующий запрос, сопоставляя любую строку от выбранного человека (p1) строке с тем же выбором еды от другого человека (p2) и оттуда для всех других вариантов выбора этого человека (p3):
SELECT DISTINCT p3.*
FROM FoodPreference AS p1
JOIN FoodPreference AS p2
ON (p1.FoodCat = p2.FoodCat AND p1.FoodChoice = p2.FoodChoice
AND p1.PersonID != p2.PersonID)
JOIN FoodPreference AS p3
ON (p2.PersonID = p3.PersonID AND p2.FoodCat != p3.FoodCat)
WHERE p1.PersonID = {(int)$chosen_person_id}
AND p1.FoodCat IN ('milk', 'bread', 'cheese');
Список «молоко», «хлеб», «сыр» в предложении WHERE - это то, что вам нужно встроить в свой PHP-код на основе переменной $_POST в вашем приложении. Если флажок установлен, включите эту категорию продуктов питания в список.
<?php
$food_cat_array = array("'none'");
$legal_food_cats = array('milk'=>1, 'bread'=>1, 'cheese'=>1, ...);
foreach (array_intersect_key($_POST, $legal_food_cats) as $key => $checked) {
if ($checked) {
$food_cat_array[] = "'$key'";
}
}
$in_predicate = join(',', $food_cat_array);
Привет, Билл. Большое вам спасибо, похоже, вы много обдумали этот ответ. Моя таблица, к сожалению, уже починена. Я мог бы дублировать данные в другом, но очень хочу избежать этого, если это возможно. Можем ли мы поработать над ответом Томалака. Я добиваюсь этого. Я бросил еду ...
И теперь я использую свои фактические значения. Не уверен, правильно ли я сравниваю. Смотрите мой новый код ниже. Получение некоторых ошибок mysql. Недействительный ресурс результата и т. д.
$sql = mysql_query("
SELECT
*
FROM ".$prefix."_users
WHERE username !='$username'
AND req_country = IFNULL(NULLIF($bcountry, ''), req_country)
AND req_region = IFNULL(NULLIF($bregion, ''), req_region)
AND req_type = IFNULL(NULLIF($btype, ''), req_type)
AND req_beds = IFNULL(NULLIF($bbeds, ''), req_beds)
AND req_value = IFNULL(NULLIF($bvalue, ''), req_value)
AND country = IFNULL(NULLIF($scountry, ''), country)
AND region = IFNULL(NULLIF($sregion, ''), region)
AND type = IFNULL(NULLIF($stype, ''), type)
AND beds = IFNULL(NULLIF($sbeds, ''), beds)
AND value = IFNULL(NULLIF($svalue, ''), value)
AND pool = IFNULL(NULLIF($spool, ''), 'Yes')
AND garage = IFNULL(NULLIF($sgarage, ''), >0)
AND disabled = IFNULL(NULLIF($sdisabled, ''), 'Yes')");
$num = mysql_num_rows($sql);
echo "Total matches ($num): <br><br>";
while($row = mysql_fetch_array($sql)){...etc
Имейте в виду, что AND имеет более высокий приоритет, чем OR. Вероятно, вам стоит добавить в скобки девять терминов гаража.
это должно быть «req_country = IFNULL (NULLIF ('$ bcountry', ''), req_country)» и так далее. Также, как сказал Билл, все условия «ИЛИ» должны быть заключены в один набор заключающих скобок.
Спасибо. Я редактировал код, как он теперь выглядит? Пул и Отключено хранятся в базе данных как Да и Нет. Я хочу, чтобы эти строки были выбраны только в том случае, если флажок установлен и установлено значение Да; так я сделал это правильно или это должно быть нет? Также могу я просто сказать> 0 для гаража?
Нет, здесь нельзя сказать> 0, это недопустимый синтаксис. Попробуйте заменить термин гараж на: CASE IFNULL ($ sgarage, '') WHEN '' THEN garage IN (0,1,2,3,4,5,6,7,8,9) ELSE garage = $ sgarage END
@Nigel: Я думаю, вам нужно больше времени уделять изучению SQL (и PHP). Без обид, но ты видел довольно ... ну ... не обученный этому. Мы показали вам, что делать, я думаю, вам просто нужно больше времени, чтобы соединить биты.
хе-хе ... Ты так прав, Томалак. Я не занимался программированием 25 лет, когда я мог делать что угодно в Sinclair ZX81 basic !! Тем не менее, я начинаю это понимать. Я понял эту проблему, спасибо за вашу помощь и Билл, ура. Взгляни на мой код. Работает отлично, ребята, недоработки?
case "display_results":
if ($bcountry = !isset($_POST["bcountry"])){
$bcountry = "No";
}else {
$bcountry = "Yes";
}
if ($bregion = !isset($_POST["bregion"])){
$bregion = "No";
}else {
$bregion = "Yes";
}
if ($btype = !isset($_POST["btype"])){
$btype = "No";
}else {
$btype = "Yes";
}
if ($bbeds = !isset($_POST["bbeds"])){
$bbeds = "No";
}else {
$bbeds = "Yes";
}
if ($bvalue = !isset($_POST["bvalue"])){
$bvalue = "No";
}else {
$bvalue = "Yes";
}
if ($scountry = !isset($_POST["scountry"])){
$scountry = "No";
}else {
$scountry = "Yes";
}
if ($sregion = !isset($_POST["sregion"])){
$sregion = "No";
}else {
$sregion = "Yes";
}
if ($stype = !isset($_POST["stype"])){
$stype = "No";
}else {
$stype = "Yes";
}
if ($sbeds = !isset($_POST["sbeds"])){
$sbeds = "No";
}else {
$sbeds = "Yes";
}
if ($svalue = !isset($_POST["svalue"])){
$svalue = "No";
}else {
$svalue = "Yes";
}
if ($spool = !isset($_POST["spool"])){
$spool = "No";
}else {
$spool = "Yes";
}
if ($sgarage = !isset($_POST["sgarage"])){
$sgarage = "No";
}else {
$sgarage = "Yes";
}
if ($sdisabled = !isset($_POST["sdisabled"])){
$sdisabled = "No";
}else {
$sdisabled = "Yes";
}
$result = mysql_query("SELECT * FROM ".$prefix."_users WHERE username!='$username'
AND (('$bcountry'='Yes' AND req_country= '$country') OR ('$bcountry'='No'))
AND (('$bregion'='Yes' AND req_region= '$region') OR ('$bregion'='No'))
AND (('$btype'='Yes' AND req_type= '$type') OR ('$btype'='No'))
AND (('$bbeds'='Yes' AND req_beds= '$beds') OR ('$bbeds'='No'))
AND (('$bvalue'='Yes' AND req_value= '$value') OR ('$bvalue'='No'))
AND (('$scountry'='Yes' AND country= '$req_country') OR ('$scountry'='No'))
AND (('$sregion'='Yes' AND region= '$req_region') OR ('$sregion'='No'))
AND (('$stype'='Yes' AND type= '$req_type') OR ('$stype'='No'))
AND (('$sbeds'='Yes' AND beds= '$req_beds') OR ('$sbeds'='No'))
AND (('$svalue'='Yes' AND value= '$req_value') OR ('$svalue'='No'))
AND (('$spool'='Yes' AND pool= 'Yes') OR ('$spool'='No'))
AND (('$sgarage'='Yes' AND garage>=1 ) OR ('$sgarage'='No'))
AND (('$sdisabled'='Yes' AND disabled= 'Yes') OR ('$sdisabled'='No'))
")or die("MySQL ERROR: ".mysql_error());
$number = mysql_num_rows($result);
Я бы хотел, чтобы флажки оставались отмеченными после отображения результатов поиска (чтобы люди могли видеть, что они выбрали). Я пробовал добавить $ ticked1, $ ticked2 и т. д. К параметрам флажка, а затем if ($ bcountry == 'Yes') {$ ticked1 = 'Checked'} и т. д., Но это не работает. Любая помощь?
Может быть, еще можно показать, как вы планируете хранить эту информацию в базе данных? Как бы выглядели таблицы?