Cambiar dinámicamente qué tabla seleccionar con la sentencia CASE de SQL
-
20-08-2019 - |
Pregunta
Estoy tratando de escribir un procedimiento almacenado y, dependiendo de un cierto valor de columna, quiero poder cambiar la tabla de la que selecciono. Trataré de dar un ejemplo:
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
Como puede ver, no solo estoy cambiando dinámicamente la tabla que selecciono, sino que dado que estas dos tablas fueron hechas en dos momentos diferentes por dos personas diferentes, los nombres de las columnas también son diferentes.
Entonces, mi pregunta es: ¿Cuál es la mejor manera de lograr esto, ya que a SQL Server no parece gustarle mi consulta que he construido?
Si alguien que ve lo que estoy tratando de hacer puede sugerir una mejor manera de hacerlo, sería todo oídos :-)
Solución
No puede usar la declaración CASE en la cláusula FROM, pero puede usar lo siguiente en su lugar:
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'
Otros consejos
Puede intentar crear la instrucción SQL dinámica como una cadena y luego llamar al procedimiento almacenado sp_executesql para ejecutar la cadena.
Consulte aquí para obtener más información y ejemplos.
No estoy seguro de por qué quiere hacer cosas en una declaración SQL. No soy una persona de SQL Server, pero en un procedimiento almacenado de Oracle podría escribir algo como esto
If itemtype = 'A'
Then
<statement for table A>
Else
<statement for Table B>
End if
Algo como esto también debería funcionar en SQL Server ... ¿tal vez alguien podría ampliar esto?
Realmente no estás explicando de dónde viene ItemType
. Como se sugiere, UNION
podría ser aplicable si simplemente combina dos tablas.
Aquí hay otra posibilidad que puede estar relacionada con su 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
Es mejor utilizar la consulta UNION para unir primero las tablas y luego SELECCIONAR.
Además, puede considerar crear una vista para una de las tablas, de modo que extraiga solo las columnas que necesita mientras las renombra, luego UNION y luego seleccione desde UNION.
O use una tabla temporal para almacenar el resultado de cada consulta. Ponga la creación de la tabla temporal en un CASO (pseudocódigo, no probado):
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