Pregunta

Tengo una pregunta acerca de la reutilización de datos de la tabla, sino un punto de vista no funcionará en este escenario ya que tengo un parámetro que debe transmitirse. Básicamente esta parte del sistema requiere un travellerid para ser enviados al procedimiento y una lista de arreglistas devuelto para que el viajero específica. Hay alrededor de 7 reglas de negocio que se utilizan para determinar qué arreglistas pueden ser devueltos y son mutuamente excluyentes, por lo que con el fin de acomodar estas reglas opcionales he utilizado una serie de las uniones dentro de una consulta derivada. Esto está funcionando bien, y el rendimiento parece bien a través de una base de datos bastante grande, sin embargo tengo que volver a utilizar estas reglas (sindicatos) en aproximadamente 4 otras partes del sistema.

Al principio me trató de crear una vista con estos sindicatos, pero que no funcionó debido a la lógica que difieren en cada Unión y diferentes requisitos de los parámetros, así que estaba pensando que tal función podría resolver este problema? Si he creado una función que tuvo @travellerid como un parámetro y devuelve una lista de arrangerid basado en las reglas de negocio, esto sería una solución ideal / rápido? Actualmente estoy usando UNION ALL y una clara en la consulta externa, ya que demostró ser mucho más rápido que el uso de la unión de la singularidad de los datos.

Procedimiento actual con las reglas de negocio a continuación (SQL Server 2008):

CREATE PROCEDURE [dbo].[getArrangersForTraveller]
   @travellerid int
AS
  DECLARE @costcentreid int
  DECLARE @departmentid int

-- Shorthand the traveller costcentre and department for use in queries below
SET @costcentreid = (SELECT costcentreid FROM traveller WHERE id = @travellerid)
SET @departmentid = (SELECT departmentid FROM traveller WHERE id = @travellerid)


SELECT DISTINCT t.id, t.firstname, t.lastname, ti.name AS title, dv.preferred
FROM traveller t

INNER JOIN title ti ON t.titleid = ti.id
     INNER JOIN

     (

            -- Get Preferred Arrangers linked to Department Groups
            SELECT dg.arrangerid as id
            FROM departmentGroup dg 
                INNER JOIN department_departmentGroup ddg 
                ON (dg.id = ddg.departmentGroupId AND ddg.departmentid = @departmentid)

            UNION ALL

            -- Get Preferred Arrangers linked to Cost Centre Groups
            SELECT cg.arrangerid as id
            FROM costCentreGroup cg 
                INNER JOIN costcentre_costCentreGroup ccg 
                ON (cg.id = ccg.costCentreGroupId AND ccg.costcentreid = @costcentreid)

            UNION ALL

            -- If Cost Centre Group has a linked department and this department matches 
            -- the travel arrangers department then return these travel arrangers as well     
            SELECT t3.id
            FROM costCentreGroup cg1

                INNER JOIN costcentre_costCentreGroup ccg1 
                ON (cg1.id = ccg1.costCentreGroupId AND ccg1.costcentreid = @costcentreid) 

                INNER JOIN traveller t3  
                ON t3.departmentid = cg1.departmentid    

            WHERE  t3.accesslevelid > 1       

            UNION ALL

            -- Get Direct linked travel arrangers      
            SELECT t1.travelarrangerid as id
            FROM   travelarranger_traveller t1
            WHERE  t1.travellerid = @travellerid

            UNION ALL

            -- Get Cost Centre linked arrangers
            SELECT tc.travelarrangerid as id
            FROM   travelArranger_costcentre tc 
            WHERE  tc.costcentreid = @costcentreid

            UNION ALL

            -- Get Department linked arrangers
            SELECT td.travelarrangerid
            FROM   travelArranger_department td 
            WHERE  td.departmentid = @departmentid

            UNION ALL

            -- Get Company flagged arrangers 
            SELECT t2.id
            FROM   traveller t2
                   INNER JOIN company c ON t2.companyid = c.id

            WHERE  t2.accesslevelid > 1       
            AND ((c.allowTravelArrangerDepartmentAccess = 1 AND t2.departmentid = @departmentid)
            OR  (c.allowTravelArrangerCostCentreAccess = 1 AND t2.costcentreid = @costcentreid))

     ) as dv ON dv.id = t.id

WHERE t.accessLevelid > 1 -- arranger or manager
AND t.isenabled = 1
ORDER BY dv.preferred DESC, t.lastname, t.firstname;
¿Fue útil?

Solución

  

Al principio me trató de crear una vista con estos sindicatos, pero que no funcionó debido a la lógica que difieren en cada Unión y diferentes requisitos de los parámetros, así que estaba pensando tal vez una función podría resolver este problema? Si he creado una función que tuvo como @travellerid parámetro y devuelve una lista de arrangerid de basado en las reglas de negocio, esto sería una solución ideal / rápido?

usted está pensando procedimiento de programación / OO, pero SQL se establece en función.
Una función funcionaría, pero se aseguraría de que un índice no podía utilizarse cuando se utiliza la función de los criterios de decisión / etc. Una vista no materializada es sólo ligeramente mejor; en SQL Server existe la opción de utilizar una vista indizada (También conocido como materializó vista) pero se ven limitados notoriamente. Va en contra de los conceptos de programación modular, pero funciona mejor cuanto menos SQL intenta modularizar y utilizar sólo lo que realmente necesita.

Me re-escribió la consulta, pero se dio cuenta de que la columna dv.preferred se hace referencia en la consulta externa, pero no está presente en el interior. Siendo que dv es un conglomerado de varias tablas y la lógica, el valor id ser devuelto no es de ningún valor real fuera de la consulta interna, ya que había necesidad de saber qué tabla el valor de procedencia. Dicho esto, aquí está:

SELECT t.id, t.firstname, t.lastname, ti.name AS title /*, dv.preferred */
  FROM TRAVELLER t
  JOIN title ti ON t.titleid = ti.id
 WHERE (EXISTS(SELECT NULL -- Get Preferred Arrangers linked to Department Groups
                 FROM departmentGroup dg 
                 JOIN department_departmentGroup ddg ON ddg.departmentGroupId = dg.id 
                                                    AND ddg.departmentid = @departmentid
                WHERE dg.arrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Preferred Arrangers linked to Cost Centre Groups
                FROM costCentreGroup cg 
                JOIN costcentre_costCentreGroup ccg ON ccg.costCentreGroupId = cg.id 
                                                   AND ccg.costcentreid = @costcentreid
               WHERE cg.arrangerid = t.id)
    OR EXISTS(SELECT NULL -- If Cost Centre Group has a linked department and this department matches the travel arrangers department then return these travel arrangers as well     
                FROM costCentreGroup cg1
                JOIN costcentre_costCentreGroup ccg1 ON ccg1.costCentreGroupId = cg1.id 
                                                    AND ccg1.costcentreid = @costcentreid
                JOIN traveller t3 ON t3.departmentid = cg1.departmentid    
                                 AND  t3.accesslevelid > 1
               WHERE t3.id = t.id)
    OR EXISTS(SELECT NULL  -- Get Direct linked travel arrangers    
                FROM travelarranger_traveller t1
               WHERE t1.travellerid = @travellerid
                 AND t1.travelarrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Cost Centre linked arrangers
                FROM travelArranger_costcentre tc 
               WHERE tc.costcentreid = @costcentreid
                 AND tc.travelarrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Department linked arrangers
                FROM travelArranger_department td 
               WHERE td.departmentid = @departmentid
                 AND td.travelarrangerid = t.id)
    OR EXISTS(SELECT NULL -- Get Company flagged arrangers 
                FROM traveller t2
                JOIN company c ON t2.companyid = c.id
                              AND t2.accesslevelid > 1       
               WHERE (   (c.allowTravelArrangerDepartmentAccess = 1 AND t2.departmentid = @departmentid)
                      OR (c.allowTravelArrangerCostCentreAccess = 1 AND t2.costcentreid = @costcentreid))
                 AND t2.id = t.id))
   AND t.accessLevelid > 1 -- arranger or manager
   AND t.isenabled = 1
ORDER BY /*dv.preferred DESC,*/ t.lastname, t.firstname;

El uso de una subconsulta (EN, EXISTE) aliviará el problema duplicados que viene con el uso se une si hay más de un registro para niños fijado a la matriz.

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