come posso interrogare più tabelle SQL per una coppia chiave-valore specifica?

StackOverflow https://stackoverflow.com/questions/104230

  •  01-07-2019
  •  | 
  •  

Domanda

Situazione: un'applicazione PHP con più moduli installabili crea una nuova tabella nel database per ciascuno, nello stile di mod_A, mod_B, mod_C ecc. Ognuno ha la colonna section_id.

Ora sto cercando tutte le voci per uno specifico section_id, e spero che ci sia un altro modo oltre a " Select * da mod_a, mod_b, mod_c ... mod_xyzzy dove section_id = value " ... o anche peggio , utilizzando una query separata per ciascun modulo.

È stato utile?

Soluzione

Se le tabelle cambiano nel tempo, puoi incorporare il codice della tua soluzione in un SP (pseudo codice - dovrai compilare):

SET @sql = ''

DECLARE CURSOR FOR
SELECT t.[name] AS TABLE_NAME
FROM sys.tables t
WHERE t.[name] LIKE 'SOME_PATTERN_TO_IDENTIFY_THE_TABLES'

- o questo

DECLARE CURSOR FOR
SELECT t.[name] AS TABLE_NAME
FROM TABLE_OF_TABLES_TO_SEACRH t

START LOOP

IF @sql <> '' SET @sql = @sql + 'UNION ALL '
SET @sql = 'SELECT * FROM [' + @TABLE_NAME + '] WHERE section_id=value '

END LOOP

EXEC(@sql)

Ho usato questa tecnica di tanto in tanto, quando non esiste un modo ovvio per renderla a prova di futuro senza SQL dinamico.

Nota: nel tuo ciclo, puoi usare il trucco di propagazione COALESCE / NULL e lasciare la stringa come NULL prima del ciclo, ma non è così chiaro se non hai familiarità con il linguaggio:

SET @sql = COALESCE(@sql + ' UNION ALL ', '')
    + 'SELECT * FROM [' + @TABLE_NAME + '] WHERE section_id=value '

Altri suggerimenti

Che dire?

SELECT * FROM mod_a WHERE section_id=value
UNION ALL
SELECT * FROM mod_b WHERE section_id=value
UNION ALL
SELECT * FROM mod_c WHERE section_id=value

Ho due suggerimenti.

  1. Forse devi consolidare tutte le tue tabelle. Se contengono tutti la stessa struttura, allora perché non avere uno "master"? tabella dei moduli, che aggiunge solo una nuova colonna che identifica il modulo (" A " ;, " B " ;, " C " ;, ....)

    Se le tabelle dei moduli sono per lo più uguali, ma hai alcune colonne diverse, potresti comunque essere in grado di consolidare tutte le informazioni comuni in una tabella e mantenere tabelle specifiche del modulo più piccole con tali differenze. Quindi avresti solo bisogno di unirti a loro.

    Questo suggerimento presuppone che la tua query nella colonna section_id menzionata sia super critica per cercare rapidamente. Con una query ottieni tutte le informazioni comuni e con un secondo otterrai tutte le informazioni specifiche se ne avessi bisogno. (E potresti non farlo - per esempio se stavi cercando di convalidare l'esistenza della sezione, trovarla nella tabella comune sarebbe sufficiente)

  2. In alternativa puoi aggiungere un'altra tabella che associ section_id ai moduli in cui si trovano.

    section_id | module
    -----------+-------
          1    |  A
          2    |  B
          3    |  A
         ...   | ...
    

    Ciò significa che devi eseguire due query, una contro questa tabella di mapping e un'altra sulla tabella del modulo per estrarre tutti i dati utili.

    Puoi estendere questa tabella con altre colonne e indici su quelle colonne se devi cercare altre colonne comuni a tutti i moduli.

    Questo metodo ha il netto svantaggio che i dati sono duplicati.

Forse alcune informazioni aggiuntive potrebbero essere d'aiuto, ma sembra che tu abbia già la soluzione. Dovrai selezionare da tutte le tabelle con un section_id. È possibile utilizzare i join anziché un elenco di tabelle, unendosi a section_id. Ad esempio

select a.some_field, b.some_field.... 
from mod_a a
inner join mod_b b on a.section_id = b.section_id
...
where a.section_id = <parameter>

Puoi anche comprimerlo come vista. Notare anche l'elenco dei campi anziché *, che consiglierei se si intendesse effettivamente utilizzare *.

Bene, ci sono solo tanti modi per aggregare informazioni da più tabelle. Puoi unirti, come hai già detto nel tuo esempio, oppure puoi eseguire più query e unirle insieme come nella risposta di borjab. Non so se l'idea di creare una tabella che interseca tutte le tabelle dei moduli ti sarebbe utile, ma se section_id fosse su una tabella del genere, saresti in grado di ottenere tutto da una singola query. Altrimenti, applaudo alla tua pigrizia, ma ho paura di dire che non vedo alcun modo di rendere quel lavoro desideroso :)

Stavo per suggerire lo stesso pensiero di Borjab. L'unico problema è che dovrai aggiornare tutte queste query se aggiungi un'altra tabella. L'unica altra opzione che vedo è una procedura memorizzata.

Ho pensato a un'altra opzione qui, o almeno a un modo più semplice per presentarlo. Puoi anche utilizzare una vista a queste tabelle multiple per farle apparire come una, e quindi la tua query sembrerebbe più pulita, più facile da capire e non dovresti riscrivere una query di unione lunga quando volevi fare altre query su queste più tabelle.

SELECT * FROM (
    SELECT * FROM table1
    UNION ALL
    SELECT * FROM table2
    UNION ALL
    SELECT * FROM table3
) subQry
WHERE field=value

Un'opzione dal lato del database sarebbe quella di creare una vista di UNION ALL delle varie tabelle. Quando aggiungi una tabella, dovrai aggiungerla alla vista, ma in caso contrario sembrerebbe una singola tabella.

CREATE VIEW modules AS (
    SELECT * FROM mod_A
    UNION ALL 
    SELECT * FROM mod_B
    UNION ALL 
    SELECT * FROM mod_C
);

select * from modules where section_id=value;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top