2011-01-29 5 views
7

Io non credo che ci sia un modo semplice per fare questo, ma sulla remota possibilità che ci sia ...dato risultati desiderati e le informazioni del database, programically costruire una query SQL che dà questi risultati

mi viene data un numero di elenchi di circa 10000 record ciascuno da una tabella di record di 10 milioni. I dati sono attualmente generati da query su vari elementi non indicizzati. Voglio creare automaticamente query che danno gli stessi risultati, utilizzando dieci campi separati indicizzati.

Esiste un algoritmo noto per la costruzione di qualcosa di simile? Oltre le basi di includere ogni 'nodo' indicizzato con il proprio OR, voglio dire.

Per esempio, supponendo che i dati voluto è:

Letter, Number 
A, 1 
A, 2 
B, 1 
C, 2 

e il database originale ha

Letter, Number 
A, 1 
A, 2 
A, 3 
B, 1 
C, 1 
C, 2 
D, 1 
D, 3 

mi piacerebbe qualcosa di simile:

WHERE ((Letter = 'A' OR Letter = 'B') AND (Number = 1 OR Number = 2)) 
OR (Letter = 'C' and Number = 2) 

O forse

WHERE (Letter IN ('A', 'B', 'C') AND Number IN (1, 2) 
AND NOT (Number = 1 AND Letter = 'C')) 

Ma io pensare Preferirei non avere

WHERE (Letter = 'A' AND Number = '1') OR 
(Letter = 'A' AND Number = '2') OR 
(Letter = 'B' AND Number = '1') OR 
(Letter = 'C' AND Number = '2') 

- a meno che gli esperti di database qui pensano che sarebbe molto più ottimizzato nel lungo periodo, per la dimensione del campione di cui stiamo parlando . Il tempo di esecuzione delle query è importante; il tempo di esecuzione dello strumento di conversione non lo è. Inoltre, non ho bisogno di ottenere necessariamente la risposta "migliore"; 'abbastanza buono' è accettabile.

Il mio piano attuale è quello di contare, ordinare e scorrere alla ricerca di cose che possono essere raggruppati insieme, per cercare di fare il minor numero di 'raggruppamenti' possibile; Penso che non preferirei avere diecimila (A e B e C e D e E e F e G e H e I e J) s 'ORed insieme.

Pensieri? Consigli degli esperti?

+0

Qualsiasi idea su come taggare questo, anche apprezzato. Non è davvero una domanda SQL, tanto quanto una questione indipendente dalla lingua che si verifica in uno spazio SQL. Probabilmente dovrei separare la riflessione sull'ottimizzazione in qualche altro posto; Sono più interessato all'algoritmo, qui. – Trevel

+0

Ho aggiunto il tag "Algoritmo". Potrebbe esserci uno specifico algoritmo denominato o un problema denominato che si adatta a questo, ma non so cosa potrebbe essere. –

+0

Tutte queste query genereranno un piano di query equivalente sulla maggior parte dei database. I DB non possono fare disgiunzioni in modo efficiente. –

risposta

0

Una soluzione potrebbe essere quella di utilizzare Tranne sugli scenari che non si desidera:

Select Letter, Number 
From Table 
Except 
    (
    Select 'A', 3 
    Union All 
    Select 'C', 1 
    Union All 
    Select Distinct 'D', Number 
    From Table 
    ) 

Un'altra soluzione sarebbe quella di popolare semplicemente una tabella temporanea con l'elenco dei valori esclusi e utilizzare Tranne che contro.

aggiunta

La natura del l'algoritmo utilizzato per determinare i criteri non è chiaro. Troverà elementi da includere o escludere? Le mie due soluzioni iniziali presuppongono che tu stia creando un elenco di esclusioni. Tuttavia, se stai costruendo una lista di inclusioni allora ovviamente puoi usare Intersect. Inoltre, si potrebbe essere in grado di fare la lista più piccola utilizzando i valori costruttore:

Select Letter, Number 
From Table 
Intersect 
Select * 
From (Values('A',1) 
    , ('A',2), ('A',3), ('B',1), ('C',2)) 

Come con il Tranne scenario, sarà probabilmente più veloce per popolare una tabella temporanea con la combinazione che si desidera e query che .

1

Spiacente, questo non è davvero una risposta alla tua domanda, ma piuttosto le mie riflessioni sul problema.

Suggerirei di memorizzare gli elenchi in una tabella separata. Ciò ti consentirà di eseguire una selezione unificata tra le due tabelle alla fine. È possibile utilizzare o meno indici nella tabella dei filtri, in base ai test delle prestazioni con i dati.

L'implementazione esatta sarebbe diversa a seconda del particolare RDMBS che si intende utilizzare. Nel mio esempio resterò fedele a Oracle, poiché è ciò che conosco meglio.

CREATE TABLE t_filter_lists (
    f_letter varchar2(1), 
    f_number number 
); 

-- Optionally, create an index: 
CREATE INDEX ix_filter_lists 
ON t_filter_lists (
    f_letter, 
    f_number 
); 

INSERT INTO t_filter_lists (f_letter, f_number) VALUES ('A', 1); 
INSERT INTO t_filter_lists (f_letter, f_number) VALUES ('A', 2); 
INSERT INTO t_filter_lists (f_letter, f_number) VALUES ('B', 1); 
INSERT INTO t_filter_lists (f_letter, f_number) VALUES ('C', 2); 
COMMIT; 

-- (Oracle-specific part) gather statistics on the filter table 
EXEC DMBS_STATS.GATHER_TABLE_STATS(... 

-- Run your query 
SELECT * 
FROM t_your_table t 
    INNER JOIN t_filter_lists f 
     ON f.f_letter = t.t_letter 
     AND f.f_number = t.t_number; 

Il vantaggio di questa soluzione è che, dato che le statistiche di tabella e l'indice sono completi e fresco, non si avrà il mal di testa di scegliere l'ordine corretto dei predicati a seconda di quale e quanto le colonne sono indicizzate, in quale ordine, qual è la loro valutazione della cardinalità ecc. L'ottimizzatore farà questo lavoro per voi, e dovrebbe essere abbastanza buono.

0

Questo non è realmente possibile senza ulteriori limitazioni al problema. Esiste un numero letteralmente infinito di criteri di filtro che è possibile utilizzare per selezionare un set di righe da un database e non è semplicemente possibile valutarli tutti. Ad esempio, supponiamo che la vista sia costruita da righe i cui ID sono primi, o il cui hash SHA1 termina con 0 - potresti ragionevolmente aspettarti che qualsiasi procedura automatizzata sia in grado di scoprire queste regole?

Inoltre, date solo le righe corrispondenti, non c'è alcun modo per essere sicuri che nessuna regola creata non selezioni anche record aggiuntivi dal database che non corrispondono - il set positivo da solo non è sufficiente.

+0

Hai le informazioni del database. E no, non mi aspetterei che riprenda i numeri primi - il punto è che NON c'è una "Risposta corretta" disponibile dai dati. È un casino di dati per lo più casuali e voglio trovare regole per descriverlo in base ai campi indicizzati. – Trevel

+0

@Trevel Quindi la generazione di risposte per lo più corrette è accettabile? I falsi positivi sono a posto? Falsi negativi? Cosa dovrebbe fare il sistema se non riesce a trovare una soluzione? –

+0

I falsi positivi/negativi identificabili sono accettabili, come si dice "non c'è una buona risposta". – Trevel

Problemi correlati