2013-05-08 14 views
5

Ecco cosa sto cercando di realizzare: 1. Estrarre l'ID utente dalla tabella utenti (documents.ownerID è la chiave esterna di Users.Handle) 2. Per gli utenti che non hanno un record che è stato creato nella tabella documenti negli ultimi 90 giorniSQL "Dove non esiste" non restituisce alcuna riga

Ecco la query che ho finora (sto facendo funzionare questo tramite SQL Management Studio 2012):

Select Users.UserID 
From Documents 
Inner Join Users on documents.OwnerID = users.handle 
Where Not Exists 
(
Select * 
From Documents 
Where documents.creationtime >= Dateadd(day, -90, getutcdate()) 
) 
Group by Users.UserID 
Order by Users.UserID ASC 

Nulla viene restituito nell'output. Tuttavia, quando rimuovo il "Not" dall'istruzione "Not Exists" ottengo un output di utenti che hanno un record creato nella tabella dei documenti negli ultimi 90 giorni. Inoltre, se cambio l'indicatore "> =" su "=", ricevo anche l'output. Penso che il problema sia che non ho una chiara comprensione dell'affermazione di EXIST. Apprezzo molto il tuo aiuto.

risposta

1

Se la query nel tuo NOT EXISTS restituisce QUALSIASI riga, otterrai 0 righe indietro. Stai dicendo "restituiscimi le righe se questa query non restituisce nulla"

EDIT: E sì, Gordon ha l'idea giusta sotto. Si vuole dire "dammi le righe per questo utente se questa query restituisce nulla per questo utente"

EDIT 2: e sotto intendevo sopra :)

+0

La mia comprensione di "Non esiste" è che la query restituirà tutto ciò che non è incluso nella sub-query, è corretto? Quindi, se l'utente non avesse avuto un record creato in 90 giorni, sarebbe stato restituito nella mia specifica query (dopo le modifiche decise da Gordon, o ovviamente), giusto? Grazie per l'aiuto. – user2124571

+0

Sì, di solito vuoi collegare la subquery NOT EXISTS alla tua query principale. Quindi nella tua versione originale dicevi "fammi registrare se non ci sono file nei documenti degli ultimi 90 giorni". In Gordon's, sta dicendo "prendi tutti i record il cui utente non ha un documento correlato degli ultimi 90 giorni". Spero che questo abbia aiutato. – Aushin

+0

E 'stato assolutamente d'aiuto, grazie !! – user2124571

8

Il motivo è perché il subquery non è correlato. Quindi, la clausola where sta dicendo: dove non esiste alcun record nei documenti con un tempo di creazione superiore a 90 giorni. Esistono tali record, quindi la clausola where fallisce sempre.

La mia ipotesi è che tu voglia questo per utente. Se è così, quindi provare questo where clausola:

where not exists (select * 
        from documents d2 
        where d2.creationtime >= Dateadd(day, -90, getutcdate()) and 
         d2.OwnerId = users.handle 
       ) 
+0

L'istruzione 'EXISTS' è una di quelle interessanti in cui può effettivamente fare riferimento a set di dati al di fuori delle sue parentesi. È consentito per la ragione stessa di essere in grado di correlarlo a un altro set di dati. –

+0

Questo ha funzionato per me, grazie mille! – user2124571

3

Un modo è quello di mettere la tabella Documents all'interno della subquery unico, rimuoverlo dalla query esterna, rendendo così la sottoquery un correlato uno:

SELECT Users.UserID 
FROM Users 
WHERE NOT EXISTS 
    (
    SELECT * 
    FROM Documents 
    WHERE Documents.OwnerID = Users.handle 
     AND Documents.creationtime >= Dateadd(day, -90, getutcdate()) 
    ) ; 

In questo modo, è anche possibile liberarsi dello GROUP BY gratuitamente.

2

Una scorciatoia per ottenere gli stessi risultati senza l'utilizzo di un sub-query sarebbe quella di utilizzare una sinistra aderire e verificare la presenza di NULL nella tabella Documenti in questo modo:

SELECT Users.UserID 
FROM Users 
LEFT JOIN Documents on documents.OwnerID = users.handle 
    AND documents.creationtime >= Dateadd(day, -90, getutcdate()) 
WHERE Documents.OwnerID IS NULL 
ORDER BY Users.UserID ASC 
Problemi correlati