2009-10-30 6 views
0

Ceci est une suite de # 1644748 où j'ai répondu avec succès à ma propre question, mais Quassnoi m'a aidé à réaliser que c'était la mauvaise question. Il m'a donné une solution qui fonctionnait pour mes données d'exemple, mais je ne pouvais pas le replacer dans la procédure stockée parente car j'échoue à la syntaxe SQL 2005. Donc, voici une tentative pour peindre l'image plus large et demander ce dont j'ai réellement besoin.TSQL conditionnellement sélectionner valeur spécifique

Cela fait partie d'une procédure stockée qui renvoie une liste d'éléments dans une application de suivi de bogues dont j'ai hérité. Il y a plus de 100 champs et 26 jointures, donc je ne retire que les bits les plus pertinents.

SELECT 
tickets.ticketid, 
tickets.tickettype, 
tickets_tickettype_lu.tickettypedesc, 
tickets.stage, 
tickets.position, 
tickets.sponsor, 
tickets.dev, 
tickets.qa, 
DATEDIFF(DAY, ticket_history_assignment.savedate, GETDATE()) as 'daysinqueue' 
FROM 
dbo.tickets WITH (NOLOCK) 
LEFT OUTER JOIN dbo.tickets_tickettype_lu WITH (NOLOCK) ON tickets.tickettype = tickets_tickettype_lu.tickettypeid 
LEFT OUTER JOIN dbo.tickets_history_assignment WITH (NOLOCK) ON tickets_history_assignment.ticketid = tickets.ticketid 
AND tickets_history_assignment.historyid = (
SELECT 
    MAX(historyid) 
FROM 
    dbo.tickets_history_assignment WITH (NOLOCK) 
WHERE 
    tickets_history_assignment.ticketid = tickets.ticketid 
GROUP BY 
    tickets_history_assignment.ticketid 
) 
WHERE 
tickets.sponsor = @sponsor 

La zone d'intérêt est le désordre de sous-requête daysinqueue. Le tableau tickets_history_assignment semble à peu près comme suit

declare @tickets_history_assignment table (
historyid int, 
ticketid int, 
sponsor int, 
dev int, 
qa int, 
savedate datetime 
) 

insert into @tickets_history_assignment values (1521402, 92774,20,14, 20, '2009-10-27 09:17:59.527') 
insert into @tickets_history_assignment values (1521399, 92774,20,14, 42, '2009-08-31 12:07:52.917') 
insert into @tickets_history_assignment values (1521311, 92774,100,14, 42, '2008-12-08 16:15:49.887') 
insert into @tickets_history_assignment values (1521336, 92774,100,14, 42, '2009-01-16 14:27:43.577') 

Chaque fois qu'un billet est enregistré, les valeurs actuelles de commanditaire, dev et qa sont stockées dans la table tickets_history_assignment avec le TicketID et un horodatage. Il est donc possible pour quelqu'un de changer la valeur de qa, mais laissez le sponsor seul. Ce que je veux savoir, basé sur toutes ces conditions, est l'historique de l'enregistrement dans la table tickets_history_assignment où la valeur du sponsor a été modifiée pour que je puisse calculer la valeur de daysinqueue. Si un enregistrement est inséré dans la table d'historique et que seule la valeur qa a changé, je ne veux pas cet enregistrement. Donc simplement compter sur MAX(historyid) ne fonctionnera pas pour moi. Quassnoi est venu avec ce qui suit a semblé fonctionner avec mes données d'échantillon, mais je ne peux pas le brancher dans la requête plus grande, les chiennes de gestionnaire de SQL au sujet de l'instruction de WITH.

;WITH rows AS 
     (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY ticketid ORDER BY savedate DESC) AS rn 
     FROM @Table 
     ) 
SELECT rl.sponsor, ro.savedate 
FROM rows rl 
CROSS APPLY 
     (
     SELECT TOP 1 rc.savedate 
     FROM rows rc 
     JOIN rows rn 
     ON  rn.ticketid = rc.ticketid 
       AND rn.rn = rc.rn + 1 
       AND rn.sponsor <> rc.sponsor 
     WHERE rc.ticketid = rl.ticketid 
     ORDER BY 
       rc.rn 
     ) ro 
WHERE rl.rn = 1 

j'ai joué avec hier après-midi et nous avons obtenu nulle part parce que je ne comprends pas fondamentalement ce qui se passe ici et comment il devrait s'intégrer dans le contexte plus large.

Alors, tout preneur?

MISE À JOUR

Ok, voici la chose. J'ai changé certains noms de tables et de colonnes pour tenter de simplifier les choses, alors voici le désordre complet non édité.

snip - vieux mauvais Code

Voici les erreurs:

Msg 102, Level 15, State 1, Procedure usp_GetProjectRecordsByAssignment, Line 159 
Incorrect syntax near ';'. 
Msg 102, Level 15, State 1, Procedure usp_GetProjectRecordsByAssignment, Line 179 
Incorrect syntax near ')'. 

Les numéros de ligne ne sont évidemment pas correct, mais se réfèrent à

;WITH rows AS 

Et ') CHAR après le WHERE rl.rn = 1

) 

Respectivement

est-il une étiquette pour super longue question supplémentaire?

MISE À JOUR # 2

Voici la requête terminée pour tous ceux qui peuvent avoir besoin ceci:

CREATE PROCEDURE [dbo].[usp_GetProjectRecordsByAssignment] 
(
    @assigned numeric(18,0), 
    @assignedtype numeric(18,0) 
) 
AS 

SET NOCOUNT ON 

WITH rows AS 
     (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY recordid ORDER BY savedate DESC) AS rn 
     FROM projects_history_assignment 
     ) 
SELECT projects_records.recordid, 
     projects_records.recordtype, 
     projects_recordtype_lu.recordtypedesc, 
     projects_records.stage, 
     projects_stage_lu.stagedesc, 
     projects_records.position, 
     projects_position_lu.positiondesc, 
     CASE projects_records.clientrequested 
      WHEN '1' THEN 'Yes' 
      WHEN '0' THEN 'No' 
     END AS clientrequested, 
     projects_records.reportingmethod, 
     projects_reportingmethod_lu.reportingmethoddesc, 
     projects_records.clientaccess, 
     projects_clientaccess_lu.clientaccessdesc, 
     projects_records.clientnumber, 
     projects_records.project, 
     projects_lu.projectdesc, 
     projects_records.version, 
     projects_version_lu.versiondesc, 
     projects_records.projectedversion, 
     projects_version_lu_projected.versiondesc AS projectedversiondesc, 
     projects_records.sitetype, 
     projects_sitetype_lu.sitetypedesc, 
     projects_records.title, 
     projects_records.module, 
     projects_module_lu.moduledesc, 
     projects_records.component, 
     projects_component_lu.componentdesc, 
     projects_records.loginusername, 
     projects_records.loginpassword, 
     projects_records.assistedusername, 
     projects_records.browsername, 
     projects_browsername_lu.browsernamedesc, 
     projects_records.browserversion, 
     projects_records.osname, 
     projects_osname_lu.osnamedesc, 
     projects_records.osversion, 
     projects_records.errortype, 
     projects_errortype_lu.errortypedesc, 
     projects_records.gsipriority, 
     projects_gsipriority_lu.gsiprioritydesc, 
     projects_records.clientpriority, 
     projects_clientpriority_lu.clientprioritydesc, 
     projects_records.scheduledstartdate, 
     projects_records.scheduledcompletiondate, 
     projects_records.projectedhours, 
     projects_records.actualstartdate, 
     projects_records.actualcompletiondate, 
     projects_records.actualhours, 
     CASE projects_records.billclient 
      WHEN '1' THEN 'Yes' 
      WHEN '0' THEN 'No' 
     END AS billclient, 
     projects_records.billamount, 
     projects_records.status, 
     projects_status_lu.statusdesc, 
     CASE CAST(projects_records.assigned AS VARCHAR(5)) 
      WHEN '0' THEN 'N/A' 
      WHEN '10000' THEN 'Unassigned' 
      WHEN '20000' THEN 'Client' 
      WHEN '30000' THEN 'Tech Support' 
      WHEN '40000' THEN 'LMI Tech Support' 
      WHEN '50000' THEN 'Upload' 
      WHEN '60000' THEN 'Spider' 
      WHEN '70000' THEN 'DB Admin' 
      ELSE rtrim(users_assigned.nickname) + ' ' + rtrim(users_assigned.lastname) 
     END AS assigned, 
     CASE CAST(projects_records.assigneddev AS VARCHAR(5)) 
      WHEN '0' THEN 'N/A' 
      WHEN '10000' THEN 'Unassigned' 
      ELSE rtrim(users_assigneddev.nickname) + ' ' + rtrim(users_assigneddev.lastname) 
     END AS assigneddev, 
     CASE CAST(projects_records.assignedqa AS VARCHAR(5)) 
      WHEN '0' THEN 'N/A' 
      WHEN '10000' THEN 'Unassigned' 
      ELSE rtrim(users_assignedqa.nickname) + ' ' + rtrim(users_assignedqa.lastname) 
     END AS assignedqa, 
     CASE CAST(projects_records.assignedsponsor AS VARCHAR(5)) 
      WHEN '0' THEN 'N/A' 
      WHEN '10000' THEN 'Unassigned' 
      ELSE rtrim(users_assignedsponsor.nickname) + ' ' + rtrim(users_assignedsponsor.lastname) 
     END AS assignedsponsor, 
     projects_records.clientcreated, 
     CASE projects_records.clientcreated 
      WHEN '1' THEN 'Yes' 
      WHEN '0' THEN 'No' 
     END AS clientcreateddesc, 
     CASE projects_records.clientcreated 
      WHEN '1' THEN rtrim(clientusers_createuser.firstname) + ' ' + rtrim(clientusers_createuser.lastname) + ' (Client)' 
      ELSE rtrim(users_createuser.nickname) + ' ' + rtrim(users_createuser.lastname) 
     END AS createuser, 
     projects_records.createdate, 
     projects_records.savedate, 
     projects_resolution.sitesaffected, 
     projects_sitesaffected_lu.sitesaffecteddesc, 
     DATEDIFF(DAY, projects_history_assignment.savedate, GETDATE()) as 'daysinqueue', 
     projects_records.iOnHitList, 
     projects_records.changetype 
FROM 
    dbo.projects_records WITH (NOLOCK) 
    LEFT OUTER JOIN dbo.projects_recordtype_lu WITH (NOLOCK) ON projects_records.recordtype = projects_recordtype_lu.recordtypeid 
    LEFT OUTER JOIN dbo.projects_stage_lu WITH (NOLOCK) ON projects_records.stage = projects_stage_lu.stageid 
    LEFT OUTER JOIN dbo.projects_position_lu WITH (NOLOCK) ON projects_records.position = projects_position_lu.positionid 
    LEFT OUTER JOIN dbo.projects_reportingmethod_lu WITH (NOLOCK) ON projects_records.reportingmethod = projects_reportingmethod_lu.reportingmethodid 
    LEFT OUTER JOIN dbo.projects_lu WITH (NOLOCK) ON projects_records.project = projects_lu.projectid 
    LEFT OUTER JOIN dbo.projects_version_lu WITH (NOLOCK) ON projects_records.version = projects_version_lu.versionid 
    LEFT OUTER JOIN dbo.projects_version_lu projects_version_lu_projected WITH (NOLOCK) ON projects_records.projectedversion = projects_version_lu_projected.versionid 
    LEFT OUTER JOIN dbo.projects_sitetype_lu WITH (NOLOCK) ON projects_records.sitetype = projects_sitetype_lu.sitetypeid 
    LEFT OUTER JOIN dbo.projects_module_lu WITH (NOLOCK) ON projects_records.module = projects_module_lu.moduleid 
    LEFT OUTER JOIN dbo.projects_component_lu WITH (NOLOCK) ON projects_records.component = projects_component_lu.componentid 
    LEFT OUTER JOIN dbo.projects_browsername_lu WITH (NOLOCK) ON projects_records.browsername = projects_browsername_lu.browsernameid 
    LEFT OUTER JOIN dbo.projects_osname_lu WITH (NOLOCK) ON projects_records.osname = projects_osname_lu.osnameid 
    LEFT OUTER JOIN dbo.projects_errortype_lu WITH (NOLOCK) ON projects_records.errortype = projects_errortype_lu.errortypeid 
    LEFT OUTER JOIN dbo.projects_resolution WITH (NOLOCK) ON projects_records.recordid = projects_resolution.recordid 
    LEFT OUTER JOIN dbo.projects_sitesaffected_lu WITH (NOLOCK) ON projects_resolution.sitesaffected = projects_sitesaffected_lu.sitesaffectedid 
    LEFT OUTER JOIN dbo.projects_gsipriority_lu WITH (NOLOCK) ON projects_records.gsipriority = projects_gsipriority_lu.gsipriorityid 
    LEFT OUTER JOIN dbo.projects_clientpriority_lu WITH (NOLOCK) ON projects_records.clientpriority = projects_clientpriority_lu.clientpriorityid 
    LEFT OUTER JOIN dbo.projects_status_lu WITH (NOLOCK) ON projects_records.status = projects_status_lu.statusid 
    LEFT OUTER JOIN dbo.projects_clientaccess_lu WITH (NOLOCK) ON projects_records.clientaccess = projects_clientaccess_lu.clientaccessid 
    LEFT OUTER JOIN dbo.users users_assigned WITH (NOLOCK) ON projects_records.assigned = users_assigned.userid 
    LEFT OUTER JOIN dbo.users users_assigneddev WITH (NOLOCK) ON projects_records.assigneddev = users_assigneddev.userid 
    LEFT OUTER JOIN dbo.users users_assignedqa WITH (NOLOCK) ON projects_records.assignedqa = users_assignedqa.userid 
    LEFT OUTER JOIN dbo.users users_assignedsponsor WITH (NOLOCK) ON projects_records.assignedsponsor = users_assignedsponsor.userid 
    LEFT OUTER JOIN dbo.users users_createuser WITH (NOLOCK) ON projects_records.createuser = users_createuser.userid 
    LEFT OUTER JOIN dbo.clientusers clientusers_createuser WITH (NOLOCK) ON projects_records.createuser = clientusers_createuser.userid 
    LEFT OUTER JOIN dbo.projects_history_assignment WITH (NOLOCK) ON projects_history_assignment.recordid = projects_records.recordid 
    AND projects_history_assignment.historyid = (
     SELECT ro.historyid 
     FROM rows rl 
     CROSS APPLY 
       (
       SELECT TOP 1 rc.historyid 
       FROM rows rc 
       JOIN rows rn 
       ON  rn.recordid = rc.recordid 
         AND rn.rn = rc.rn + 1 
         AND rn.assigned <> rc.assigned 
       WHERE rc.recordid = rl.recordid 
       ORDER BY 
         rc.rn 
       ) ro 
     WHERE rl.rn = 1 
       AND rl.recordid = projects_records.recordid 
    ) 

WHERE 
    (@assignedtype='0' and projects_records.assigned = @assigned) 
OR (@assignedtype='1' and projects_records.assigneddev = @assigned) 
OR (@assignedtype='2' and projects_records.assignedqa = @assigned) 
OR (@assignedtype='3' and projects_records.assignedsponsor = @assigned) 
OR (@assignedtype='4' and projects_records.createuser = @assigned) 
+0

"Les chiots concernant l'instruction WITH" ne sont pas très descriptifs. Quel est le message d'erreur exact? – Quassnoi

+0

Oh, désolé .. c'était "syntaxe incorrecte près du mot-clé 'AVEC'." C'est pourquoi je n'ai pas mis le message spécifique, car il est vague. J'ai remplacé la requête dans AND tickets_history_assignment.historyid =() par la vôtre. Eh bien d'abord il a dit la syntaxe incorrecte près de ';'. Puis j'ai enlevé le ';' et alors ça n'aimait pas 'AVEC'. – Dzejms

+0

Je viens de copier collé la déclaration et cela fonctionne parfaitement. Pourriez-vous copier et coller le contenu ** exact ** de la fenêtre 'Management Studio' ici? Je veux dire exact, c'est la seule façon de gérer les erreurs de syntaxe. – Quassnoi

Répondre

0
WITH rows AS 
     (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY ticketid ORDER BY savedate DESC) AS rn 
     FROM @Table 
     ) 
SELECT projects_records.recordid, 
     projects_records.recordtype, 
     /* skipped */ 
     AND projects_history_assignment.historyid = (
     SELECT ro.historyid 
     FROM rows rl 
     CROSS APPLY 
       (
       SELECT TOP 1 rc.savedate 
       FROM rows rc 
       JOIN rows rn 
       ON  rn.recordid = rc.recordid 
         AND rn.rn = rc.rn + 1 
         AND rn.assigned <> rc.assigned 
       WHERE rc.recordid = rl.recordid 
       ORDER BY 
         rc.rn 
       ) ro 
     WHERE rl.rn = 1 
       AND rl.recordid = projects_records.recordid 
     ) 
+0

Ok, je l'ai eu à travailler, mais il faut maintenant 25 secondes pour exécuter la requête par opposition à .2 avant. Je suppose que je vais essayer de penser à une autre façon de stocker ces données. Peut-être que je vais ajouter une autre colonne pour savoir si l'utilisateur assigné ne sera pas modifié ou quelque chose comme ça. Merci pour toute votre aide et désolé pour vos problèmes. – Dzejms

+0

'@ Dzejms': La sous-requête ici est corrélée et est réévaluée pour chaque ligne, c'est pourquoi cela prend tellement de temps. Vous devez le remplacer par un JOIN. – Quassnoi

+0

Je ne sais pas quelle sous-requête remplacer avec une jointure ou comment j'accomplirais cela. Faites-vous référence à la section «CROSS APPLY»? – Dzejms

0

Eh bien, si cette requête ne fonctionne pas - vous pouvez toujours envisager un déclencheur sur la tickets_history_assignment table. Vous pouvez utiliser INSTEAD OF INSERT, UPDATE qui se déclenche avant que des modifications ne soient apportées, afin que vous ayez un contrôle total de ce qui est sur le point de changer et de ce qu'il faut faire.

Questions connexes