2014-02-25 124 views
1

我有兩個實體:Proposal和Vote。我可以SQL連接兩次表嗎?

  • 提案:用戶可以提出建議。
  • 投票:用戶可以投票提出建議。
CREATE TABLE `proposal` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `title` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`), 
); 

CREATE TABLE `vote` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `idea_id` int(11) NOT NULL, 
    `updated` datetime NOT NULL, 
    PRIMARY KEY (`id`), 
); 

現在我想獲取上升Propsals,這意味着:

  • 提案標題
  • 的所有時間票
  • 已收到內過去三天票總數

我想取不帶子SELECT be因爲我使用不允許sub SELECT s的教義。所以,我的方法是通過結合vote的桌子兩次(第一次爲取票的總金額,第二要能夠創建一個WHERE子句過去三天中篩選)來獲取和做INNER JOIN

SELECT 
    p.title, 
    COUNT(v.p_id) AS votes, 
    DATEDIFF(NOW(), DATE(x.updated)) 
FROM proposal p 
JOIN vote v ON p.id = v.p_id 
INNER JOIN vote x ON p.id = x.p_id 
WHERE DATEDIFF(NOW(), DATE(x.updated)) < 3 
GROUP BY p.id 
ORDER BY votes DESC; 

很明顯,這將返回一個錯誤的votes金額,因爲它將選票'COUNT()三倍。它實際上是2^n,因爲它創建了一個笛卡爾產品,就像CROSS JOIN一樣。

有沒有什麼辦法可以在不使用子SELECT的情況下獲得適當的金額?

+0

爲什麼不執行兩個查詢,後來「加盟」呢? :-) – Smutje

+0

@Smutje - 爲什麼不把所有的數據保存在CSV或文本文件中,並將它們加入到內存中? – MatBailie

+0

因爲SQL提供了一種查詢數據的好方法 - 但是我對於如何在DBMS技術中存儲業務邏輯沒有一個可行且易於理解的解決方案的想法太強烈厭惡。 – Smutje

回答

1

相反,你可以創建一個使用這種模式的一種COUNTIF功能:
- COUNT(CASE WHEN <condition> THEN <field> ELSE NULL END)

例如...

SELECT 
    p.title, 
    COUNT(v.p_id) AS votes, 
    COUNT(CASE WHEN v.updated >= DATEADD(DAY, -3, CURRENT_DATE()) THEN v.p_id ELSE NULL END) AS new_votes 
FROM 
    proposal p 
JOIN 
    vote  v 
    ON p.id = v.p_id 
GROUP BY 
    p.title 
ORDER BY 
    COUNT(v.p_id) DESC 
; 
+0

是的,非常好的方法。謝謝! –

相關問題