2010-02-14 45 views
1

我有一個SQL查詢將歷史價格信息組合在一起。它不是特別乾淨,可能可以優化很多。其中一個原因是,我使用子查詢通過子查詢獲取「以前的」價格值,並將其分配給別名「last_value」。理想情況下,我希望能夠在查詢WHERE子句中使用此別名,而不必重新執行查找。有關SQL別名的條件邏輯

我明白爲什麼這是不可能的(據我瞭解,SQL查詢是從右到左進行解析的,在數據​​輸回前應用了別名)。我只是想在這裏發帖詢問是否可以用其他方法使這樣的事情成爲可能。

具體來說,我很想通過SQL來計算p.value(當前值)和last_value(最後一個值)之間的百分比差異,而不是在應用程序層執行。

我曾考慮將百分比差異作爲表格本身的單獨列存儲,但這似乎稍微向後(考慮到所涉及的邏輯微不足道,唯一的絆腳石是使用別名)。

我正在使用MySQL。

$sql = "SELECT 
       t.*, 
       p.value, 
       p.timestamp, 
       (SELECT 
        value 
       FROM 
        prices 
       WHERE 
        prices.id = p.id AND 
        prices.country=':country' AND 
        prices.timestamp < p.timestamp 
       ORDER BY 
        prices.timestamp DESC 
       LIMIT 1) AS last_value 
      FROM 
       prices AS p, 
       titles AS t 
      WHERE 
       t.row_id = p.id AND 
       p.country = ':country' AND 
       p.current = 1 AND 
       (SELECT 
        value 
       FROM 
        prices 
       WHERE 
        prices.id = p.id AND 
        prices.country=':country' AND 
        prices.timestamp < p.timestamp 
       ORDER BY 
        prices.timestamp DESC 
       LIMIT 1) IS NOT NULL 
      ORDER BY 
       p.timestamp DESC 
      LIMIT :offset, :limit"; 
+0

哪個DBMS?每個人的答案都會大不相同。 – Aaronaught 2010-02-14 16:37:07

+0

對不起,應該有具體說明。 MySQL的。 – ndg 2010-02-14 17:19:00

回答

2

我從來沒有實際使用MySQL,但是在SQL Server中我會做這樣的事情:

SELECT (last.value - current.value)/last.value AS percentage 
FROM (SELECT ....) AS last 
INNER JOIN (SELECT ...) AS current 
ON last.PK = current.PK 

它仍然可能在MySQL的工作,因爲這幾乎是standad SQL-92,我相信。這裏有一個關於這個MySQL文檔的鏈接: http://dev.mysql.com/doc/refman/5.0/en/unnamed-views.html

0

亞歷山大有正確的想法(我不能投票,因爲我已經註冊了一個適當的Stackoverflow帳戶)。我最終使用的SQL:

SELECT 
        current.*, 
        last.value AS last_value 
       FROM 
        (SELECT 
         t.*, 
         p.id AS p_id, 
         p.value, 
         p.timestamp 
        FROM 
         prices AS p, 
         titles AS t 
        WHERE 
         t.row_id = p.id AND 
         p.country = ':country' AND 
         p.current = 1 
        ) current 
       INNER JOIN 
        (SELECT 
         prices.* 
        FROM 
         prices 
        WHERE 
         prices.country = ':country' AND 
         prices.current = 0 
        ORDER BY 
         prices.timestamp DESC) last 
        ON 
         last.id = current.p_id AND 
         last.timestamp < current.timestamp 
       GROUP BY 
        current.row_id 
       ORDER BY 
        current.timestamp DESC, 
        current.name ASC 
       LIMIT :offset, :limit