2009-07-13 9 views
0

Ich verstehe es nicht? Ich sehe keinen Ort, um eine "Union All" in der Syntax auszuführen. Was vermisse ich?Fehler: Rekursiver allgemeiner Tabellenausdruck 'EmailLog' enthält keinen UNION ALL-Operator auf oberster Ebene

CREATE PROCEDURE SapUser_NdaysBeforeExpirationNotification 
    -- Add the parameters for the stored procedure here 
(
    @AuditTypeKey nvarchar(50), 
    @TimeLapseInMonths int 
) 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    With AuditResults(SapUserId) 
    AS 
    (
     Select SapUserId From Audit 
     Where TypeKey = @AuditTypeKey And DATEDIFF(month, AttemptDate, GETDATE()) < 2 
    ) 


    Select * from SapUser 
    Inner Join Audit On vw_SapUser_Retrieve.SapId <> AuditResults.SapUserId 
    Where DATEDIFF(month, OriginalTrainingDate, GETDATE()) > @TimeLapseInMonths 

END 

Audit Tabelle (aka EmailLog)

CREATE TABLE [dbo].[Audit](
    [AuditId] [int] NOT NULL, 
    [TypeKey] [nvarchar](50) NOT NULL, 
    [Description] [nvarchar](250) NULL, 
    [AuditDate] [datetime] NOT NULL, 
    [SapUserId] [int] NOT NULL, 
CONSTRAINT [PK_EmailLog] PRIMARY KEY CLUSTERED 

Tabelle SAPUSER

CREATE TABLE [dbo].[SapUser](
    [SapId] [int] IDENTITY(70000,1) NOT NULL, 
    [Username] [nvarchar](10) NULL, 
    [Password] [nvarchar](50) NOT NULL, 
    [FirstLogin] [bit] NOT NULL, 
    [Roles] [tinyint] NOT NULL, 
    [Status] [nvarchar](20) NOT NULL, 
    [Title] [nvarchar](20) NULL, 
    [FirstName] [nvarchar](50) NOT NULL, 
    [LastName] [nvarchar](50) NOT NULL, 

... etc

Problemdetails

Ich habe zwei Tabellen: SapUser und EmailLog. Wenn ein Benutzer in einem bestimmten Zeitraum keine Aktion ausführt, wird sein Konto gelöscht. In Schritten von 90, 60, 30, 7, 1 Tag sende ich eine E-Mail, die sie daran erinnert, etwas zu unternehmen.

Jedes Mal, wenn ich eine E-Mail sende, protokolliere ich sie in der "Audit" -Tabelle (war Emaillog). Da nicht alle Monate 30 Tage sind, ist es möglich, dass eine Person zwei 90-Tage-Benachrichtigungen erhält. Um dies zu verhindern, füge ich eine Zeile in die Audit-Tabelle ein.

Wenn ich die Routine ausführen, um Konten für E-Mails zu finden, suche ich zuerst alle Konten in der Audit-Tabelle, die ich in den letzten N (90, 60, 30 ..etc) Tagen gesendet habe und entferne sie aus der Betrachtung .

+0

Wo kommt EmailLog hinein? Der Fehler scheint zu sein, dass ein CTE namens EmailLog erwartet wird. Aber Sie scheinen auch nicht die CTE AuditResults zu verwenden ... Verwenden Sie Synonyme? – gbn

+0

Mein Fehler, ich habe EmailLog in Audit umbenannt. Ich habe alle Verweise auf den alten Tabellennamen im obigen Code entfernt. –

Antwort

1

Im ursprünglichen Code, Sie haben:

Select * from SapUser 
Inner Join Audit On vw_SapUser_Retrieve.SapId <> AuditResults.SapUserId 
Where DATEDIFF(month, OriginalTrainingDate, GETDATE()) > @TimeLapseInMonths 

Dies ist die einzige Zeit ist, dass Sie den CTE AuditResults bezeichnet und es sollte wie ein Tisch sein, nicht als Funktion. Es sei denn, das "Audit" in dieser Zeile sollte "AuditResults" sein (und SapUser ist wahrscheinlich auch vw_SapUser_Retrieve).

Wie auch immer, es ist möglich, dass die Fehlermeldung irreführend ist, weil die CTE-Referenz falsch verwendet wird.

Sie haben es trotzdem behoben, aber ich denke, ich kann sehen, was schiefgelaufen ist

+0

Danke für das Aussehen! –

+0

Eigentlich wollte ich * aus der Ansicht "vw_SapUser_Retrieve" auswählen. Es war spät. –

1
With EmailLog(SapUserId) 
AS 
(
    Select SapUserId 
    From EmailLog 
    Where TypeKey = @EmailLogKey 
    And DATEDIFF(month, AttemptDate, GETDATE()) < 2 
) 

Dies ist ein rekursiver CTE. Rekursive CTEs haben eine spezifische Form, wählen aus einer Achro-Union den gesamten rekursiven Teil (in einem Join). Bist du sicher, dass die FROM korrekt ist? Sollte es SapUser sein?

+0

5k rep woot, geht ins Bett –

+0

Herzlichen Glückwunsch! –

0

Ich entfernte das CTE und erstellte eine SQL-Anweisung. Ich glaube, das ist dasselbe, der CTE war leichter zu verstehen. Hoffentlich habe ich diese einzelne SQL-Anweisung korrekt.

Select * from vw_SapUser_Retrieve 
Inner Join Audit On vw_SapUser_Retrieve.SapId = Audit.SapUserId 
Where DATEDIFF(month, OriginalTrainingDate, GETDATE()) > @TimeLapseInMonths AND (Audit.TypeKey <> @AuditTypeKey OR (Audit.TypeKey = @AuditTypeKey AND DATEDIFF(month, Audit.AuditDate, GETDATE()) > 2)) 
Verwandte Themen