2011-10-14 229 views
1

首先查詢:合併兩個SELECT查詢

$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(); 

正如你可以看到,我選擇在差不多兩個查詢相同的字段。問題是條件。

是否有可能在一個查詢中生成它?

+0

做的結果集是否包含記錄中的重疊? – Randy

+0

下次發佈模式。 – Jauzsika

+0

所以告訴我們,你想用第一個和第二個查詢來實現什麼。在第一個查詢中,我假設您查找最新的論壇和它的創建者。在第二個,你尋找日期的東西... – Jauzsika

回答

1
$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) "; 

您的代碼

逃離
我會建議使用一個避開功能,只有一個評論。
它簡化了您的代碼,並且無需擔心列是int還是字符串。
如果您只是使用mysql_real_escape_string()(或mysqli_real....()(以適用者爲準))並且記得總是引用您的$變量,那麼您可以在任何地方使用相同的轉義。
它使你的代碼更清潔。

可讀性問題
我不知道怎麼了反所有反引號。
對我來說,它看起來像你嘔吐所有的查詢。
如果標識符是保留字_(或包含空格等),則只需要反引號。

語法錯誤
不僅如此,但你使用沒有定義,這是一個語法錯誤的別名。

隱式連接是一個反模式
您使用隱式SQL連接,這是壞的形式,容易出錯和混亂。
改爲使用顯式連接,它將幫助您避免意外的交叉連接並清除where子句以提高可讀性。

如果它叫起來像鴨子....
如果查詢(幾乎)同樣的事情,最好讓它看起來相同。
你說查詢A選擇論壇中的第一篇文章,查詢B選擇最後一篇文章。
這些結果非常相似,但查詢佈局非常不同。
這聽起來像一個代碼氣味,應該避免。

+0

我在讀'使用'UNION'不是最好的主意。你怎麼看?另外,我正在使用PDO,所以它可以提供更好的想法? – Cyclone

+0

@Cyclone:'UNION'有時不好,但在這種情況下絕對不是,它只是將兩個查詢聯合起來,每個查詢返回1行。 –

0

這樣的事情(和任何時候,我需要建立與多個可選參數類似的查詢),我通常是先建立一個字符串(:我修改查詢的整理了一下,企圖使用較少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(); 

我知道這看起來有點粗糙的(和特定的查詢,它可能是更好地與兩個不同的人堅持)。通常,當查詢返回相同的列並且僅僅是多個ANDOR語句時,這會更好。希望這有助於

+1

您剛剛在不可讀的旁邊做了一個簡單的查詢。我沒有看到這個混淆比賽的目的。 – Johan