你的第一個查詢可以被改寫爲:
SELECT b.centerBranchNumber,
b.countryCode,
a.type,
SUM(DECODE(a.status, 1, 1, 0)) filled
FROM tableA a
JOIN tableB b
ON a.branchCode = b.branchCode
JOIN tableC
ON a.registerNumber = c.registerNumber
WHERE c.registerDate <= '01.02.2013'
AND c.state = 'A'
AND c.contractState != 2
GROUP BY b.centerBranchNumber,
b.countryCode,
a.type
至於你的第二個到ANSI語法以及(它將幫助更復雜的查詢,因爲當你做錯了事情時,這是非常明顯的)它變成這樣:
SELECT b.centerBranchNumber,
b.countryCode,
a.type,
SUM(DECODE(a.status, 0, 1, 0)) free,
SUM(DECODE(a.status, 2, 1, 0)) damaged
FROM tableA a
JOIN tableB b
ON a.branchCode = b.branchCode
WHERE a.kks_kayitdrm = 'A'
AND a.recordDate <= '01.02.2013'
GROUP BY b.centerBranchNumber,
a.type,
b.countryCode
正如你所看到的兩個查詢之間存在大量的相似性。爲了得到你想要的結果集,有兩種方法。將不相似的條件移入SUM中的CASE語句。或者,你可以聯合所有這兩個查詢在一起,再次總結。我寧願使用CASE語句,因爲您減少了必須完成的工作量;缺點是查詢變得不太容易閱讀。
查詢的公共部分是:
SELECT b.centerBranchNumber,
b.countryCode,
a.type
FROM tableA a
JOIN tableB b
ON a.branchCode = b.branchCode
GROUP BY b.centerBranchNumber,
a.type,
b.countryCode
以此爲直到你得到相同的結果,你可以慢慢地添加到它的基地。您必須記住將相同的條件添加到WHERE/JOINS以確保您獲得相同的結果。
如果我們首先添加所有條件;您必須將第一個查詢中tableC上的JOIN更改爲LEFT OUTER JOIN。這與WHERE子句將結果集限制爲INNER JOIN完全相同。
SELECT b.centerBranchNumber,
b.countryCode,
a.type
FROM tableA a
JOIN tableB b
ON a.branchCode = b.branchCode
LEFT OUTER JOIN tableC
ON a.registerNumber = c.registerNumber
WHERE c.registerDate <= '01.02.2013'
AND c.state = 'A'
AND c.contractState != 2
GROUP BY b.centerBranchNumber,
b.countryCode,
a.type
添加條件,你現在需要一個或您的WHERE子句中的第二個查詢:
SELECT b.centerBranchNumber,
b.countryCode,
a.type
FROM tableA a
JOIN tableB b
ON a.branchCode = b.branchCode
LEFT OUTER JOIN tableC
ON a.registerNumber = c.registerNumber
WHERE (c.registerDate <= '01.02.2013'
AND c.state = 'A'
AND c.contractState != 2
)
OR (a.kks_kayitdrm = 'A'
AND a.recordDate <= '01.02.2013'
)
GROUP BY b.centerBranchNumber,
b.countryCode,
a.type
接下來,您的日期似乎比多了幾分陌生。您似乎沒有將字符串文字'01.02.2013'
轉換爲日期,因爲它不是YYYYMMDD形式,所以您的比較不起作用。您所依靠的NLS_DATE_FORMAT的形式爲DD.MM.YYYY
,您無法保證每次會話都能保證。要比較一個日期,您應該使用內置的TO_DATE()
函數以及相應的format model或ANSI datetime literal進行明確轉換,我在this answer中對此進行了更全面的說明。
只想說,甲骨文explicitly recommends against using implicit conversion因爲:
SQL語句是容易當你使用顯式數據類型轉換函數理解。
隱式數據類型轉換可能會對性能產生負面影響,尤其是如果將列值的數據類型轉換爲常數而非其他方式。
隱式轉換取決於它發生的上下文,並且在每種情況下可能不會以相同的方式工作。例如,從日期時間值到VARCHAR2值的隱式轉換可能會返回意外的一年,具體取決於NLS_DATE_FORMAT 參數的值。
隱式轉換的算法可能會在軟件版本和Oracle產品之間發生變化。顯式轉換的行爲更具可預測性。
要比較你的日期,因此我會建議使用TO_DATE(),例如:
WHERE (c.registerDate <= to_date('01.02.2013', 'dd.mm.yyyy')
最後,我們可以在增加的款項;這意味着重複您之前的條件。您可以簡化爲您的第一個查詢,因爲是否填充「是完全依賴於左外部連接,這意味着如果JOIN中該表的registerNumber
不是null,則條件爲真。
在這兩種情況下,我都使用CASE語句而不是DECODE;這是因爲CASE功能更強大,並且執行正確的數據類型which is not guaranteed with DECODE。
把所有這一起最終的查詢變爲:
SELECT b.centerBranchNumber
, b.countryCode
, a.type
, sum(case when a.status = 1 and c.registernumber is not null then 1
else 0
end) as filled
, sum(case when a.status = 0
and a.kks_kayitdrm = 'A'
and a.recordDate <= to_date('01.02.2013', 'dd.mm.yyyy')
then 1
else 0
end) as free
, sum(case when a.status = 2
and a.kks_kayitdrm = 'A'
and a.recordDate <= to_date('01.02.2013', 'dd.mm.yyyy')
then 1
else 0
end) as damaged
FROM tableA a
JOIN tableB b
ON a.branchCode = b.branchCode
LEFT OUTER JOIN tableC
ON a.registerNumber = c.registerNumber
WHERE (c.registerDate <= to_date('01.02.2013', 'dd.mm.yyyy')
AND c.state = 'A'
AND c.contractState != 2
)
OR (a.kks_kayitdrm = 'A'
AND a.recordDate <= to_date('01.02.2013', 'dd.mm.yyyy')
)
GROUP BY b.centerBranchNumber
, b.countryCode
, a.type
您可以使用此方法更一般的查詢相結合,它是適當的。
,非常感謝你的回答。你的asnwer很棒:) – engcmreng