2013-11-21 56 views
6

我有3個包含相似行數據的表。 我需要從所有三個表用以下條件的選擇100行:如何從3個不同的表中共同選擇100行?

不超過25行可以從表A中選擇 - >(命名爲count_a)

不超過40行可以從表B中選擇 - >(count_b)

行的任何數目的可從表C(count_c)進行選擇,但數量應該 count_c = 100 - (+ count_a count_b)

Combine 3 tables in one collection of rows

這裏是我的嘗試:

SELECT * FROM 
(
    SELECT * FROM TABLE_A WHERE ROWNUM <= 25 
    UNION ALL 
    SELECT * FROM TABLE_B WHERE ROWNUM <= 40 
    UNION ALL 
    SELECT * FROM TABLE_C 
) WHERE ROWNUM <=100 

但查詢速度太慢,並不總是給我100行。

+0

你的查詢看起來很好 - 在哪些情況下它不給100行? –

+0

正如你所說的你的條件,他們很滿意,即使你只返回表C中的100行。所以,你去:SELECT * FROM TABLE_C WHERE ROWNUM <= 100 –

回答

2

嘗試添加WHERE ROWNUM <= 100到最後的選擇:

SELECT * FROM 
(
    SELECT TABLE_A.*, 1 as OrdRow FROM TABLE_A WHERE ROWNUM <= 25 
    UNION ALL 
    SELECT TABLE_B.*, 2 as OrdRow FROM TABLE_B WHERE ROWNUM <= 40 
    UNION ALL 
    SELECT TABLE_C.*, 3 as OrdRow FROM TABLE_C WHERE ROWNUM <= 100 
) WHERE ROWNUM <=100 
    ORDER BY OrdRow; 

你也可以試試:

SELECT * FROM TABLE_A WHERE ROWNUM <= 25 
UNION ALL 
SELECT * FROM TABLE_B WHERE ROWNUM <= 40 
UNION ALL 
SELECT * FROM TABLE_C WHERE ROWNUM <= 
     100 
     - 
     (select count(*) TABLE_A WHERE ROWNUM <= 25) 
     - 
     (select count(*) TABLE_B WHERE ROWNUM <= 40) 
+0

這樣做的工作。而且性能也好很多。謝謝 – Ahmad

+0

第一個查詢是做出UNION ALLs的無理假設,優化器將始終從第一個查詢返回行,然後從第二個查詢返回行,等等。當然,這是Oracle在實踐中做的,但不能保證。 –

+0

@JeffreyKemp第一個查詢沒有做出這樣的假設。這裏UNION的順序並不重要。我們需要從3個表中返回100行,因此我們可以將TABLE_C限制爲100行。在這種情況下,即使A ansd B沒有返回行C返回100,我們將得到總計100行。 – valex

0

是...執行速度是一場噩夢每個開發人員或程序員... 在這種情況下,你可以嘗試像...我認爲它會加快你的查詢更多

DECLARE @Table_A_Row_Count INT, @Table_B_Row_Count INT,@RemainCount INT=0 

--Getting count of primary tables 
SELECT @Table_A_Row_Count= COUNT(1) FROM TABLE_A 
SELECT @Table_B_Row_Count= COUNT(1) FROM TABLE_B 

--Calculating remaining colections 
IF @[email protected]_B_Row_Count<100 
    BEGIN 
     SET @RemainCount=100-(@[email protected]_B_Row_Count) 
    END 
ELSE 
    BEGIN 
     --You might do somthing like this if First 
     --and second table covering 100 rows 
     SET @[email protected]_A_Row_Count 
    END 

--Finaly getting 100 rows 
SELECT top @Table_A_Row_Count * FROM TABLE_A 
UNION ALL 
SELECT top @Table_B_Row_Count * FROM TABLE_B 
UNION ALL 
SELECT Top @RemainCount * FROM TABLE_C 
+1

非常好的方式>我喜歡這個解決方案。但我更喜歡最簡單的,我已經接受 – Ahmad

+1

@MoumitMondal這是SQL服務器語法,不是Oracle。 –

+0

現在我明白了....感謝:D – Moumit

1

嘗試這樣,

SELECT * FROM 
(
    SELECT * FROM table_a where rownum <=25 
    UNION ALL  
    SELECT * FROM table_b WHERE ROWNUM <= 40 
    UNION ALL 
    SELECT * FROM table_c WHERE ROWNUM <= 100 - ((SELECT count(*) FROM table_a WHERE ROWNUM <= 25) + (SELECT count(*) FROM table_b WHERE ROWNUM <= 40)) 
);  
1

技術上講,你不得不做這樣的事情,以確保您始終得到TABLE_A和表-B行如果它們存在:

SELECT * FROM (
    SELECT * FROM (
    SELECT 'A' t, TABLE_A.* FROM TABLE_A WHERE ROWNUM <= 25 
    UNION ALL 
    SELECT 'B' t, TABLE_B.* FROM TABLE_B WHERE ROWNUM <= 40 
    UNION ALL 
    SELECT 'C' t, TABLE_C.* FROM TABLE_C 
) ORDER BY t 
) WHERE ROWNUM <= 100; 

這是因爲優化器允許以它喜歡的任何順序運行子查詢 - 例如在平行下。

關於性能,我懷疑sort操作不會爲執行時間增加太多時間,因爲它無論如何都只能排序最多100行。

相關問題