Pregunta

He leído sobre el uso de la expresión CASE dentro de la cláusula WHERE aquí:

http: // scottelkin. com / sql / using-a-case-statement-in-a-sql-where-clause /

Estoy tratando de usar esto para filtrar los resultados de mi declaración de selección, en base a un número de contrato que será transferido por la aplicación del usuario. Actualmente, mi código arroja un error de 'Parámetro no válido' sin importar lo que se haya pasado. Verifiqué que SELECT / FROM está funcionando bien, como en el caso de una cláusula WHERE sin una expresión CASE. Aquí está mi código.

WHERE     (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END =
tblContracts.ContractNo)

La redundancia del código es para solucionar problemas. Planeo usar el filtro de comodines en el CASE más adelante. Me estoy enfocando en bajar la sintaxis ahora mismo. Creo que esto debería devolver todos los registros para los cuales el parámetro coincide con el número de contrato almacenado en la tabla. Cualquier ayuda o consejo sería muy apreciado.

¿Fue útil?

Solución

Después de leer su explicación, hay una mejor manera de hacerlo sin CASE :

WHERE @ContractNo = 0 OR tblContracts.ContractNo = @ContractNo

Esto solo devolverá números de contrato coincidentes, a menos que @ContractNo sea 0, en cuyo caso devolverá todos los registros.

Editar: Acabo de ver que CasperOne propuso lo mismo . Yo no vi eso. Hazte grande.

Otros consejos

¿Estás seguro de que quieres hacer esto? Su declaración de caso devuelve SIEMPRE @ContractNo . Creo que lo que estás buscando es esto:

where 
    case @ContractNo 
        when 0 then tblContracts.ContractNo 
        else @ContractNo 
    end = tblContracts.ContractNo

El filtro anterior dice "dame el contrato donde el ContractNo es igual al parámetro, o todos ellos si el parámetro es 0.

El filtro anterior solo se filtra cuando el campo del número de contrato es exactamente igual al parámetro.

En cualquier caso, debes hacer esto en su lugar:

where @ContractNo = 0 or @ContractNo = tblContracts.ContractNo

La lógica es mucho más fácil de entender, y además de eso (no me cites en esto), el optimizador probablemente funcionará mejor fuera de la declaración del caso.

Intenta omitir los paréntesis que están en el lugar equivocado de todos modos, el correcto debería estar después de " FIN " ;.

¿Tal vez se olvidó de declarar @ContractNo? ¿Es comparable a 0 y a tblContracts.ContractNo?

La publicación de Recursive solucionó mi problema con precisión.

Vi quejas sobre la claridad de mi publicación original. En el futuro, ¿qué puedo hacer para que lo que digo sea más directo? No estoy acostumbrado a formular preguntas sobre el código, y me disculpo por cualquier cosa confusa que haya tenido. ¿Necesitaba proporcionar los detalles extendidos como en mi segunda publicación?

Gracias de nuevo por toda la ayuda.

Mueve tu paréntesis de cierre antes de = me gusta así:

WHERE     (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END)=tblContracts.ContractNo

No veo qué hará esta declaración de caso, sin embargo ... está devolviendo lo mismo en caso de que @ContractNo = 0 o si no lo es ...

La sintaxis correcta es:

  Select...
  ...
  Where(
    Case
      When <Condition>
        Then <Return if true>
        Else <Return if false>
      End
 ) = <Whatever is being matched to the output of the case statement>

Sin embargo, independientemente de la sintaxis, su ejemplo no tiene mucho sentido, si está buscando todos los elementos que coincidan o tengan un Número de contrato de 0, entonces lo haría:

Select...
...
Where (
  @ContractNo = 0 Or
  @ContractNo = tblContracts.ContractNo
)

Lo que parece tener mucho más sentido que para lo que intentas usar la declaración del caso.

Editar: Debo haber leído mal la pregunta, el parámetro faltante generalmente significa que el parámetro (en este caso @ContractNo) no está declarado en el alcance de su consulta / procedimiento. Pero alguien ya lo señaló, así que no puedo tomar ningún crédito por eso.

El motivo de la declaración del caso, incluido el conjunto " Si es 0, indique el parámetro, y de lo contrario, simplemente indique el parámetro " Fue para probarlo para tratar de obtener la sintaxis correcta. Originalmente, había intentado decir "Si es 0, entonces pase '%' para devolver cada valor. El código que publiqué allí era porque seguí recibiendo 'Parámetro no válido' y pensé que debía haber algún problema con mi sintaxis. Cuando lo separé en una coincidencia de parámetros básicos como tal,

WHERE @ContractNo = tblContracts.ContractNo

devolvió registros bien. Déjame explicarte un poco más.

Estoy extrayendo de un montón de tablas diferentes, y filtrando el contenido con información no incluida en la declaración de selección (es decir, tblContracts no tiene información extraída de Select, solo se usa en Dónde). El usuario seleccionará de un cuadro combinado que tendrá los diferentes números de contrato, así como un valor predeterminado de 'Todos'.

Voy a tener un evento para cuando cambie el índice del cuadro combinado. Si es 'Todo', se pasará 0 como parámetro y no quiero que se realice ningún filtrado. De lo contrario, solo quiero la información para ese número de contrato (el motivo de Else @ContractNo).

¿No quieres decir algo como esto?

SELECT * 
    FROM tblContracts
    WHERE     
    CASE 
       WHEN tblContracts.ContractNo = 0 THEN @ContractNo 
       ELSE tblContracts.ContractNo
    END = tblContracts.ContractNo

Donde @ContractNo es una variable del mismo tipo de datos que tblContracts.ContractNo

¿Por qué incluso necesitas una declaración del caso?

CUANDO @ContractNo = 0 entonces (0 = tblContracts.ContractNo) else @ContractNo entonces (@ContractNo = tblContracts.ContractNo)

Esto no tiene sentido ya que simplemente podrías escribir esto como

Donde @contractNo = tblContracts.contractNo

¿Es el número de contrato realmente un número o es una cadena que siempre resulta ser un número? Compruebe sus tipos de datos entre la tabla y el parámetro y la sentencia CASE (por ejemplo, " = 0 " o " = '0' ")

Esta sintaxis debería funcionar (lo hace en Oracle)

WHERE CASE WHEN tblContracts.ContractNo = 0 
           THEN @ContractNo 
           ELSE tblContracts.ContractNo
      END = tblContracts.ContractNo

cuando dices:

  

Estoy extrayendo de un montón de tablas diferentes, y filtrando el contenido con información no incluida en la declaración de selección (es decir, tblContracts no tiene información extraída de Select, solo se usa en Dónde). El usuario seleccionará de un cuadro combinado que tendrá los diferentes números de contrato, así como un valor predeterminado de 'Todos'.

Entonces me parece que debería tener un " Donde existe " cláusula. ¿Ya no estás sacando ninguna información de esa mesa ?!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top