Modifica dinamica della tabella da cui selezionare con l'istruzione CASE SQL
-
20-08-2019 - |
Domanda
Sto cercando di scrivere una procedura memorizzata e, a seconda di un determinato valore di colonna, voglio poter cambiare la tabella da cui seleziono. Proverò a fare un esempio:
SELECT ItemNumber,
ItemType,
Description
FROM
CASE ItemType
WHEN 'A' THEN TableA
ELSE TableB
END
WHERE
CASE ItemType
WHEN 'A' THEN ItemNumber = @itemNumber
ELSE PartNumber = @itemNumber
END
Come puoi vedere, non solo sto cambiando dinamicamente la tabella da cui seleziono, ma poiché queste due tabelle sono state create in due momenti diversi da due persone diverse, anche i nomi delle colonne sono diversi.
Quindi, la mia domanda è: qual è il modo migliore per ottenere questo risultato, dato che a SQL Server non sembra piacere la mia query che ho creato.
Se qualcuno che vede quello che sto cercando di fare può suggerire un modo migliore per farlo, sarei tutto orecchi :-)
Soluzione
Non è possibile utilizzare l'istruzione CASE nella clausola FROM, ma è invece possibile utilizzare quanto segue:
SELECT itemnumber, itemtype, description
FROM tablea
WHERE itemnumber = @itemnumber AND itemtype = 'A'
UNION ALL
SELECT itemnumber, itemtype, description
FROM tableb
WHERE partnumber = @itemnumber AND itemtype <> 'A'
Altri suggerimenti
Potresti provare a creare l'istruzione SQL dinamica come stringa e quindi chiamare la procedura memorizzata sp_executesql per eseguire la stringa.
Vedi qui per ulteriori informazioni ed esempi.
Non sono sicuro del motivo per cui vuoi fare le cose in una sola istruzione SQL .. Non sono una persona di SQL Server, ma in una procedura memorizzata Oracle potresti scrivere qualcosa del genere
If itemtype = 'A'
Then
<statement for table A>
Else
<statement for Table B>
End if
Qualcosa del genere dovrebbe funzionare anche in SQL Server .. forse qualcuno potrebbe espandersi su questo?
Non stai davvero spiegando da dove viene ItemType
. Come suggerito UNION
potrebbe essere applicabile se si stanno semplicemente combinando due tabelle.
Ecco un'altra possibilità che può riguardare il tuo problema:
SELECT ItemNumber,
ItemType,
COALESCE(TableA.Description, TableB.Description) AS Description
FROM Items
LEFT JOIN TableA
ON Items.ItemType = 'A'
AND TableA.ItemNumber = Items.ItemNumber
LEFT JOIN TableB
ON Items.ItemType <> 'A'
AND TableB.ItemNumber = Items.ItemNumber
È meglio utilizzare la query UNION per unire prima le tabelle e poi SELEZIONARE.
Inoltre, potresti prendere in considerazione la possibilità di creare una vista per una delle tabelle, in modo da estrarre solo le colonne necessarie durante la ridenominazione, quindi UNION e quindi selezionare da UNION.
Oppure usa una tabella temporanea per memorizzare il risultato di ogni query. Metti la creazione della tabella temporanea in un CASE (pseudocodice, non testato):
CASE @itemType
WHEN 'A'
SELECT ACol1 AS Col1, ACol2 AS Col2
FROM TABLE_A
INTO #tempTable
WHERE ItemNumber = @itemNumber
ELSE
SELECT BCol1 AS Col1, BCol2 AS Col2
FROM TABLE_B
INTO #tempTable
WHERE PartNumber = @itemNumber
END
SELECT * FROM #tempTable