2013-11-21 18 views
6

Ho 3 tabelle contenenti righe di dati simili. Ho bisogno di selezionare 100 righe da tutte e tre le tabelle con le seguenti condizioni:Come posso selezionare collettivamente 100 righe da 3 tabelle diverse?

non più di 25 righe possono essere selezionati dalla Tabella A -> (chiamarlo count_a)

non più di 40 righe può essere selezionato dalla Tabella B -> (count_b)

Qualsiasi numero di righe può essere selezionato dalla Tabella C (count_c), ma il numero dovrebbe essere count_c = 100 - (+ count_a count_b)

Combine 3 tables in one collection of rows

Ecco cosa ho provato:

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 

Ma la query è troppo lento e non sempre mi danno 100 righe.

+0

La query sembra corretta, in quali casi non fornisce 100 righe? –

+0

Come hai dichiarato le tue condizioni, sono soddisfatti, anche se restituisci solo 100 righe dalla tabella C. Quindi ecco qui: SELEZIONA * DA TABLE_C DOVE ROWNUM <= 100 –

risposta

2

provo ad aggiungere WHERE ROWNUM <= 100 all'ultimo selezionare:

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; 

Inoltre si può provare:

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

Questo ha funzionato. e anche le prestazioni sono molto migliori. Grazie – Ahmad

+0

La prima query sta assumendo l'ipotesi ingiustificata che, date le UNION ALL, l'ottimizzatore restituirà sempre le righe dalla prima query, seguite dalle righe della seconda query, ecc. Certo, questo è ciò che Oracle fa in pratica, ma non è garantito . –

+0

@JeffreyKemp La prima query non sta facendo questa ipotesi. L'ordine di UNION non è importante qui. Dobbiamo restituire 100 righe da 3 tabelle in modo che possiamo limitare TABLE_C con 100 righe. In questo caso, anche se A ansd B non restituisce righe C restituisce 100 e otterremo 100 righe totali. – valex

0

Sì ... La velocità di esecuzione è un incubo per tutti gli sviluppatori o programmatori ... In tal caso puoi provare come ... penso che acceleri la tua richiesta in più

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

Modo molto carino> Mi piace questa soluzione. Ma preferisco la più semplice, ho accettato sopra – Ahmad

+1

@MoumitMondal Questa è la sintassi del server SQL, non Oracle. –

+0

Ora capisco .... grazie: D – Moumit

1

Prova in questo modo,

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

Tecnicamente, si avrebbe dovuto fare qualcosa di simile, al fine di garantire che otterrai sempre le righe da TABLE_A e TABLE_B se presenti:

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; 

Questo perché l'ottimizzatore è consentito per eseguire le sottoquery nell'ordine che preferisce, ad esempio in parallelo.

Per quanto riguarda le prestazioni, ho il sospetto che l'operazione di ordinamento non aggiungerà troppo tempo al tempo di esecuzione perché è solo l'ordinamento di un massimo di 100 righe comunque.

Problemi correlati