2012-05-14 72 views
8

下載包含下載時間,下載時間標識和buno ID。 故障由故障代碼,下載時間標識,狀態和類型組成。下載可能有許多錯誤,可以通過下載時間ID加入。左側外部加入Postgres不返回空值

給定一組的故障代碼,結果必須包含每個故障代碼與對應的故障計數。如果在下載中沒有找到故障代碼,則故障代碼必須返回,故障計數爲零。

這個問題似乎需要一個OUTER JOIN,但隨着預期的Postgres,因爲它似乎並沒有與左表返回空值的設置還沒有看到這方面的工作。

查詢是下面,有一些細節爲了簡潔冷落:

SELECT f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM download_time d 
LEFT OUTER JOIN fs_fault f ON f.downloadtimeid = d.id 
    AND f.faultcode IN (1000,1100) 
    AND f.statusid IN(2, 4) 
WHERE (d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012') 
    AND d.bunoid = 166501 
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

第二天,我已經編輯以顯示答案。所有的答案都很接近,並有各種幫助。但是,JayC的答案是最接近的。 這裏是最後的SQL,有取故障代碼語句的WHERE子句中唯一的變化:

SELECT f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM download_time d 
RIGHT OUTER JOIN fs_fault f ON f.downloadtimeid = d.id 
     AND f.statusid IN(2, 4) 
     AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012' 
     AND d.bunoid = 166501 
WHERE f.faultcode IN (1000,1100) 
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

謝謝大家的幫助!喜歡這個網站!

+1

你分析了你的數據嗎?我懷疑這是PostgreSQL中的問題......請問您可以在[SQL Fiddle](http://sqlfiddle.com/)中提供表結構和示例數據嗎? – vyegorov

+1

'download_time d LEFT OUTER JOIN fs_fault f ON f.downloadtimeid = d.id'具有'download_time'作爲左表,而不是'fs_fault'。連接條件與連接中左側或右側的表無關。 – JayC

回答

20

我給我的答案,因爲我有其他答案的重大疑慮。你必須小心過濾器的要求。請記住,在您加入後,運行where子句。因此,如果在where子句中有任何涉及非外連接表的過濾器要求,則(在許多情況下)已使外連接無效。因此,採取你的sql,似乎最簡單的解決方案是要麼使用適當的連接,要麼適當地移動表名,然後將過濾條件從where子句中移出並加入join子句中。

SELECT f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM download_time d 
RIGHT OUTER JOIN fs_fault f ON 
    f.downloadtimeid = d.id 
    AND f.faultcode IN (1000,1100) 
    AND f.statusid IN(2, 4) 
    AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012') 
    AND d.bunoid = 166501 
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

,我相信應該是等價的另一種方式是

SELECT f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM download_time d 
RIGHT OUTER JOIN fs_fault f ON 
    f.downloadtimeid = d.id 
    AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012') 
    AND d.bunoid = 166501 
WHERE 
    f.faultcode IN (1000,1100) 
    AND f.statusid IN(2, 4) 
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

,因爲它沒有嚴格身在何處,在fs_fault過濾要求。 (而且你的SQL引擎會改變這一切)。

編輯:這是一個SQLFiddle演示連接子句與where子句的過濾。

+1

你對'WHERE'子句與'JOIN'條件的說法是對的。我在這方面確定了我的答案。儘管如此,我認爲你沒有解決他關於如何獲得所需故障碼的問題,即使沒有發生。 – kgrittn

+0

謝謝大家:我向所有的迴應者投了票,因爲我從每個回報中學到了一些東西。但是,JayC,你最接近。唯一的改變是將'f.faultcode IN(1000,1100)'移到where子句。在此過程中,顯示​​正確的故障代碼。謝謝,JayC! – MAbraham1

+0

我無法使SQLFiddle正常工作。我在使用IE 7.0.5730.13CO,因爲我在工作。我必須在我通常運行Chrome的家中嘗試它。 – MAbraham1

2

這將需要一個RIGHT OUTER JOIN。右外連接包括右表的所有值,其中NULL s在左表中沒有條目(我不確定這是否可以與GROUP BY一起使用,儘管...)如果fs_fault是一個表所有故障代碼。

在你的情況,fs_fault似乎包含了下載所有故障。這可能是出乎意料的行爲嗎?

1

左外連接選擇在第一個表一切加匹配行中的第二個表。第一個表格似乎包含下載嘗試。所以,來自「from」的結果包括所有下載嘗試。

但是,它並不一定包含您的所有故障代碼。發生的情況是,您對符合標準的一個或多個代碼沒有任何錯誤。

您需要的是包含所有的故障代碼,爲了這個工作表。在這裏,我只是創建一個故障代碼列表作爲第一個表格。我認爲以下查詢是這樣的:

SELECT thefaults.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM (select 1000 as faultcode union all select 1100 
    ) thefaults join 
     fs_fault f 
     on f.faultcode = thefaults.faultcode and 
     f.statusid in (2, 4) left outer join 
     download_time d 
     ON f.downloadtimeid = d.id 
WHERE (d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012') AND 
     d.bunoid = 166501 
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

我承認:我使用SQL Server語法來創建「thefaults」。

+0

如果故障代碼沒有關聯的下載時間,它將被where子句過濾掉。 – JayC

+0

有人認爲這是提問者想要的。 –

2

如果要通過的faultcode計數,這似乎是最簡單的解決方案:

WITH fc(faultcode) AS (VALUES (1000,1100)) 
SELECT fc.faultcode, count(d.downloadtimeid) as faultcount 
    FROM fc 
    LEFT JOIN (fs_fault f ON f.faultcode = fc.faultcode 
         AND f.statusid IN(2, 4) 
    JOIN download_time d ON d.id = f.downloadtimeid 
         AND d.bunoid = 166501 
         AND d.downloadtime::date BETWEEN date '2011-04-11' 
                AND date '2011-05-01') 
    GROUP BY fc.faultcode 
    ORDER BY fc.faultcode 

請注意,我一直在你的條件,其中,如果他們沒有正確的statusid或bunoid故障不計算在內。我有點害怕日期選擇可能沒有做到你想的那樣,所以我提出了另一種選擇。如果您使用TIMESTAMP WITHOUT TIME ZONE,即使這樣也可能不會達到您的要求,但這是另一回事。我還添加了ORDER BY子句,因爲您可能不希望結果的順序不一致;沒有該條款,它可能會或可能不會在GROUP BY序列中,並且可能會在沒有警告的情況下更改。

+0

如果故障代碼沒有關聯的下載時間,它將被where子句過濾掉。 – JayC

+0

糟糕。通過添加括號來強化連接評估的順序,從而進行修正。謝謝! – kgrittn

+0

@JayC在他的回答中提到了'WHERE'子句與'JOIN'條件的好點。如前所述,如果特定故障代碼的* only *行已被條件排除,則故障代碼不會出現。通過移動條件進行修復。 – kgrittn