Pregunta

Tengo que lidiar con una tabla donde hay un conjunto de campos cada uno seguido de un segundo campo que contendrá un nuevo valor sugerido hasta que se confirme este cambio.

Se parece un poco a esto:

refID    field1    newField1    field2    newField2   ... 

refID es un valor de ID que se vincula a una tabla maestra. Una fila en la tabla maestra puede tener n filas en mi tabla de detalles. Los tipos de datos incluyen ints, strings y dateTimes.

Ahora, estoy buscando tener una consulta que me diga, dada una refID, si hay algún cambio sugerido en la tabla de detalles.

Estaba jugando un poco con algunas selecciones de UNION, con COALESCE () e ISNULL () ... pero todos esos intentos parecían un poco raros en el mejor de los casos. La base de datos es MS-SQL-Server 2005.

Para aclarar mi problema:

--this is a simplification of the details table in question
CREATE TABLE [dbo].[TEST_TABLE](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [refID] [int] NOT NULL,
    [firstName] [varchar](50) NULL,
    [newFirstName] [varchar](50) NULL,
    [lastName] [varchar](50) NULL,
    [newLastName] [varchar](50) NULL
)

--here we insert a detail row ... one of many that might exist for the master table (e.g. data about the company)
insert into TEST_TABLE(refID, firstName, lastName) values(666, 'Bill', 'Ballmer')
--this is what happens when a user saves a suggested change
update TEST_TABLE SET newLastName = 'Gates' where ID = 1
--and this is what happens when this suggestion is accepted by a second user
update TEST_TABLE set lastName=newLastName, newLastName = NULL where ID = 1
¿Fue útil?

Solución

Esta es la solución más limpia que se me ocurre. Debería repetir la lógica para cada elemento de datos (col1, col2, etc.):

DECLARE @RefID int, @Changes bit

SET @Changes = 0 --No changes by default

SET @RefID = 42 --Your RefID

IF EXISTS(SELECT * FROM MyDetailTable
          WHERE RefID = @RefID
          AND (
          (Col1 IS NULL AND NewCol1 IS NOT NULL)
          OR 
          (Col1 IS NOT NULL AND NewCol1 IS NULL)
          OR
          (Col1 <> Col2)
          ))
   SET @Changes = 1

Otros consejos

Modifiqué la solución de randolphos.

 select 
        refID ,
        case when 
            newField1 is not null or
            newField2 is not null or
            ...
        then 1 else 0 end  haschanged
    from myTable
    where refID = @refID

Actualización: básicamente lo que dijo Aron Aalton en otro formato de salida.

Aquí hay una consulta simple:

    SELECT TOP 1 1 as found
      FROM [dbo].[TEST_TABLE] t
     WHERE COALESCE(t.newFirstName,t.newLastName) IS NOT NULL
       AND t.refID = 1

Esta consulta devolverá una sola fila si hay cambios propuestos para un refID (basado en el ejemplo en su pregunta).

Para su tabla real, por supuesto, necesitaría enumerar cada una de las columnas 'newValue' como argumentos en la función COALESCE. (En la lista de fusión, recomiendo explícitamente convertir cualquier VARCHAR que no sea VARCHAR, solo para dejar en claro que cada expresión en la lista es del mismo tipo de datos.

Si prefiere usar una expresión CASE en lugar de COALESCE:

    SELECT TOP 1 1 as found
      FROM [dbo].[TEST_TABLE] t
     WHERE CASE 
           WHEN t.newFirstName IS NOT NULL THEN 1
           WHEN t.newLastName  IS NOT NULL THEN 1
           ELSE NULL
           END IS NOT NULL
       AND t.refID = 1

¿Este esquema ya está definido y en producción? De lo contrario, recomendaría encarecidamente tener una tabla de 'cambios' separada de alguna descripción, tal vez use fieldname, fieldvalue donde fieldvalue es una variable sql_variant.

No creo que su estructura existente se vea bien cuando los valores sean 'aceptados' (supongo que nulos) especialmente porque no conservará ningún historial de auditoría con este enfoque.

No puedo probar esto, pero quizás:

select (field1 is not null and field2 is not null) as ChangesMade where refID = @id
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top