Объединение двух запросов SELECT - PullRequest
1 голос
/ 14 октября 2011

Первый запрос:

$fpost = $sql->query(" SELECT `p`.`name`, `f`.`id`, `f`.`topic`, `f`.`date`, `f`.`last` 
FROM `posters`, `forum` 
WHERE `f`.`deleted` = 0 
AND `f`.`neg` = ".(int) $neg['id']." 
AND `p`.`id` = `f`.`author` 
ORDER BY `f`.`last` DESC LIMIT 1")->fetch();

Второй запрос:

$lpost = $sql->query("SELECT `p`.`name`, `f`.`id`, `f`.`topic`, `f`.`date`, `a`.`access` 
FROM `forum`, `posters` 
LEFT JOIN `account` `a` ON (`a`.`id` = `p`.`aid`) 
WHERE `f`.`neg` = ".(int) $neg['id']." 
AND `p`.`id` = `f`.`author` 
AND `f`.`date` = " . (int) $fpost['last'] . " 
LIMIT 1")->fetch();

Как видите, я выбираю почти одинаковые поля в обоих запросах.Проблема в следующих условиях.

Есть ли возможность сделать это одним запросом?

Ответы [ 2 ]

1 голос
/ 14 октября 2011
$neg_id = mysql_real_escape_string($neg['id']);

$query =" (SELECT p.name, f.id, f.topic, f.date, f.last, null as access 
  FROM forum f
  INNER JOIN posters p ON (p.id = f.author)   <<-- use explicit join syntax
  WHERE f.deleted = 0 
  AND f.neg = '$neg_id' 
  ORDER BY f.date ASC                <<-- first post
  LIMIT 1 OFFSET 0)
UNION
  (SELECT p.name, f.id, f.topic, f.date, f.last, a.access 
  FROM forum f
  INNER JOIN posters p ON (p.id = f.author)
  LEFT JOIN account a ON (a.id = p.aid) 
  WHERE f.deleted = 0
  AND f.neg = '$neg_id'  
  ORDER BY f.date DESC               <<-- last post
  LIMIT 1 OFFSET 0) ";

Комментарии к вашему коду

Экранирование
Я бы посоветовал использовать одну экранирующую функцию и только одну.
Это упрощает ваш код и избавляет от необходимости беспокоиться о том, является ли столбец целым или строковым.
Если вы просто используете mysql_real_escape_string() (или mysqli_real....() в зависимости от того, что применимо) и не забываете всегда указывать свои $ vars, то вы можете использовать одно и то же экранирование везде.
Это делает ваш код намного чище.

Проблемы с читаемостью
Я понятия не имею, что случилось со всеми обратными ходами.
Мне кажется, что тебя вырвало все твои вопросы.
Обратные пометки нужны только в том случае, если идентификатор является зарезервированным словом _ (или содержит пробелы и тому подобное).

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

Неявные объединения являются антишаблоном
Вы используете неявные SQL-объединения, которые являются неправильной формой, подвержены ошибкам и сбивают с толку.
Вместо этого используйте явные объединения, это поможет вам избежать случайных перекрестных объединений и прояснит условие where, улучшая читабельность.

Если крякает как утка ....
Если запрос делает (почти) то же самое, лучше сделать так, чтобы выглядел так же.
Вы говорите, что запрос A выбирает первое сообщение на форуме, а запрос B выбирает последнее.
Эти результаты очень похожи, но структура запросов очень отличается.
Это похоже на запах кода, и его следует избегать.

0 голосов
/ 14 октября 2011

Для подобных вещей (и в любое время, когда мне нужно создать похожие запросы с несколькими необязательными аргументами), я обычно сначала строю строку ( примечание : я немного изменил порядок запроса при попыткеиспользовать меньше if операторов):

$specialQuery = isset($fpost) && isset($fpost['last']);
$query = "SELECT `p`.`name`, `f`.`id`, `f`.`topic`, `f`.`date`, ";

if($specialQuery) {
  $query .= "`a`.`access` ";
} else {
  $query .= "`f`.`last` ";
}

$query .= "FROM `posters`, `forum` ";

if($specialQuery) {
  $query .= "LEFT JOIN `account` `a` ON (`a`.`id` = `p`.`aid`) ";
}

$query .= "WHERE `f`.`neg` = ".(int) $neg['id']." ". 
          "AND `p`.`id` = `f`.`author` ";

if($specialQuery) {
  $query .= "AND `f`.`date` = " . (int) $fpost['last'] . " ".
            "LIMIT 1";
} else {
  $query .= "AND `f`.`deleted` = 0 ".
            "ORDER BY `f`.`last` DESC LIMIT 1";
}

$result = $sql->query($query)->fetch();

Я знаю, что это выглядит немного грубым (и для ваших конкретных запросов может быть лучше придерживаться двух отдельных).Обычно это работает лучше, когда запросы возвращают одинаковые столбцы и представляют собой просто несколько операторов AND или OR.Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...