Aiuto per query dove il WHERE è un'altra query

di il
38 risposte

Aiuto per query dove il WHERE è un'altra query

Ciao a tutti,
avrei bisogno di fare una quey da un database che ho creato anni fa.

L'esigenza è di estrapolare una lista di alunni che abbiano ripotato e mai recuperato una insufficienza o assenza su una o più materie.

Al momento sono riusciuto a scrivere una query che, dalla tabella "VotiAllievi" mi estrapola tutti gli alunni effettivi (quindi che non sono andati via -> transitati o dimissionari = falso) con almeno un'insufficienza o/e assenza.
1.PNG
1.PNG

SELECT AllieviAnagrafica.Cognome, AllieviAnagrafica.Nome, Corsi.Corso, Discipline.Disciplina, SessioniEsami.SessioneEsame, Esami.DataEsame, Voti.Voto, VotiAllievi.Assente
FROM ((Corsi RIGHT JOIN ((Esami RIGHT JOIN ((((VotiAllievi LEFT JOIN Voti ON VotiAllievi.IDVoto = Voti.IDVoto) LEFT JOIN AllieviCorsi ON VotiAllievi.IDAllievoCorso = AllieviCorsi.IDAllievoCorso) LEFT JOIN AllieviAnagrafica ON AllieviCorsi.IDAllievo = AllieviAnagrafica.IDAllievo) LEFT JOIN EsamiVerbali ON VotiAllievi.IDEsameVerbale = EsamiVerbali.IDEsameVerbale) ON Esami.IDEsame = EsamiVerbali.IDEsame) LEFT JOIN Curricula ON Esami.IDCurricula = Curricula.IDCurricula) ON Corsi.IDCorso = Curricula.IDCorso) LEFT JOIN Discipline ON Curricula.IDDisciplina = Discipline.IDDisciplina) LEFT JOIN SessioniEsami ON Esami.IDSessioneEsame = SessioniEsami.IDSessioneEsame
WHERE (((Voti.Voto)<18) AND ((AllieviCorsi.Transitato)=False) AND ((AllieviCorsi.Dimissionario)=False)) OR (((VotiAllievi.Assente)=True) AND ((AllieviCorsi.Transitato)=False) AND ((AllieviCorsi.Dimissionario)=False));
Il problema è che alcuni hanno già ripetuto l'esame e sono stati promossi e quindi devono essere esclusi da quella query.

Io avevo pensato di aggiungere un "WHERE" che a sua volta fa una seconda query sulla tabella "VotiAllievi" e mi seleziona (e quindi esclude dalla query principale) gli stessi allievi (IDAllievo) che hanno preso almeno 18 nella stessa materia (IDDisciplina).
La query che seleziona IDAllievo e IDDisciplina con voto maggiore a 17 sarebbe questa:
2.PNG
2.PNG

SELECT AllieviCorsi.IDAllievo, Curricula.IDDisciplina
FROM (Esami RIGHT JOIN (((VotiAllievi LEFT JOIN Voti ON VotiAllievi.IDVoto = Voti.IDVoto) LEFT JOIN AllieviCorsi ON VotiAllievi.IDAllievoCorso = AllieviCorsi.IDAllievoCorso) LEFT JOIN EsamiVerbali ON VotiAllievi.IDEsameVerbale = EsamiVerbali.IDEsameVerbale) ON Esami.IDEsame = EsamiVerbali.IDEsame) LEFT JOIN Curricula ON Esami.IDCurricula = Curricula.IDCurricula
WHERE (((Voti.Voto)>17) AND ((AllieviCorsi.Transitato)=False) AND ((AllieviCorsi.Dimissionario)=False));
Al momento per fare delle prove ho usato il "crea query" di access, ma in alternativa avevo pensato che potrei popolare una tabella di appoggio (da svuotare ogni volta) con il codice VBA associato all'evento "click" di un pulsante su una maschera.

Chi mi aiuta?

Grazie.

38 Risposte

  • Re: Aiuto per query dove il WHERE è un'altra query

    Provato ad usare un filtro?
  • Re: Aiuto per query dove il WHERE è un'altra query

    In che senso?
  • Re: Aiuto per query dove il WHERE è un'altra query

    Oggi ho provato a inserire sul campo "IdAllievo" della prima query il criterio:
    is not (SELECT....)
    copiando il codice sql della seconda query ma il risultato da 0 record.
  • Re: Aiuto per query dove il WHERE è un'altra query

    Filtri il risultato della query. Per vedere se fa al caso tuo, puoi fare una prova veloce, puoi mettere un pulsante sulla maschera dove visualizzi i risultati della query e li filtri in base al criterio che ti occorre.
  • Re: Aiuto per query dove il WHERE è un'altra query

    I filtri non fanno a caso mio...
    serve una selezione nella selezione che esclude parte dei risultati:
    la selezione deve escludere eventuali record se l'allievo in questione ha superato l'esame in seconda battuta
  • Re: Aiuto per query dove il WHERE è un'altra query

    Da quello che mi risulta i filtri fanno questo, filtrare una serie di risultati ottenuti da una query, senza dover scrivere altre query, o modificare query che vengono usate da altre parti. Non parlo dei filtri automatici con l imbuto ma quelli dove applichi una condizione where a livello di codice o di proprieta della form. Poi mi sorge un dubbio. Se già escludi quelli che hanno superato le esame, come mai non vengono esclusi anche quelli che l hanno superato in seconda battuta? Il campo che controlla se lo studente ha superato l esame dovrebbe essere univoco. Sbaglio?
  • Re: Aiuto per query dove il WHERE è un'altra query

    maxs84 ha scritto:


    I filtri non fanno a caso mio...
    serve una selezione nella selezione che esclude parte dei risultati:
    la selezione deve escludere eventuali record se l'allievo in questione ha superato l'esame in seconda battuta
    I filtri fanno proprio al caso tuo...
    Costruisci la query fatta bene senza criteri, poi nella maschera strutturi per applicare ai dati il criterio o i criteri in modo intelligente...

    Ovviamente fai quello che credi ma è un suggerimento che ti suggerisco, prima di escluderlo, quantomeno di comprenderlo... e dalla tua risposta l'esclusione è per non comprensione.
  • Re: Aiuto per query dove il WHERE è un'altra query

    Tra parentesi anche le relazioni non mi convincono. Vedo solo relazioni uno a molti, che complicano le query. Applicando la 3 forma normale sarebbe tutto più semplice. Access con le wizard è semplice per tutti, ma crea buchi enormi nella conoscenza base dei database.
    Errori che poi ci si porta dietro anche quando si padroneggia access.
  • Re: Aiuto per query dove il WHERE è un'altra query

    Non vorrei dire una baggianata, ma mi sembra di capire che la relazione tra allievi corsi e voto è molti ad uno. Quindi otterrai sempre il primo risultato. Che nel caso di un esame superato in seconda battuta sarà la ricerca ti darà sempre bocciato.
    Questo perché, se non ho sbagliato ragionamento, hai 2 superchiavi diverse che puntano solo al primo voto ottenuto dello studente, che in caso di bocciatura è minore di 17 e non considera il secondo voto positivo.
    Se cosi fosse non avrai solo problemi con questa query, ma con tutte quelle che usano voto come discriminazione.
    Poi, perché hai diviso il voto mettendolo in una tabella diversa?
    Voto a mio avviso deve essere un campo contenuto in tabella con esame, perché devi avere un voto collegato ad ogni esame, in modo che in caso di ripetizione dell esame, avrai due record diversi con due risultati diversi e sopratutto con una superchiave univoca.
    Perché, in teoria la query fa il suo dovere. Ti discrimina i promossi ed i bocciati, ma non quelli in seconda battuta, perché non hai nulla di univoco che certifichi la promozione.
  • Re: Aiuto per query dove il WHERE è un'altra query

    fratac ha scritto:


    Da quello che mi risulta i filtri fanno questo, filtrare una serie di risultati ottenuti da una query, senza dover scrivere altre query, o modificare query che vengono usate da altre parti. Non parlo dei filtri automatici con l imbuto ma quelli dove applichi una condizione where a livello di codice o di proprieta della form. Poi mi sorge un dubbio. Se già escludi quelli che hanno superato le esame, come mai non vengono esclusi anche quelli che l hanno superato in seconda battuta? Il campo che controlla se lo studente ha superato l esame dovrebbe essere univoco. Sbaglio?
    Pensavo parlassi dei filtri a imbuto...
    Al momento non ho nessuna form che si appoggia a questa query, ho costruito la query in modalità struttura e da lì volevo provare a ottenere il risultato voluto.
    Ma non capisco come dovrei strutturare il filtro di cui parli.
  • Re: Aiuto per query dove il WHERE è un'altra query

    @Alex ha scritto:


    maxs84 ha scritto:


    I filtri non fanno a caso mio...
    serve una selezione nella selezione che esclude parte dei risultati:
    la selezione deve escludere eventuali record se l'allievo in questione ha superato l'esame in seconda battuta
    I filtri fanno proprio al caso tuo...
    Costruisci la query fatta bene senza criteri, poi nella maschera strutturi per applicare ai dati il criterio o i criteri in modo intelligente...

    Ovviamente fai quello che credi ma è un suggerimento che ti suggerisco, prima di escluderlo, quantomeno di comprenderlo... e dalla tua risposta l'esclusione è per non comprensione.
    Come ho detto all'utente che mi ha proposto i filtri pensavo si parlasse dei filtri automatici a imbuto.

    Se faccio una query senza criteri otterrò praticamente tutto il contenuto della tabella "VotiAllievi".
    Da quesa base devo togliere:
    -tutti gli allievi che a oggi sono andati via (transitato o dimissionario -> vero);
    -tutti gli allievi che non hanno nessuna assenza (assente -> vero);
    -tutti gli allievi che hanno un voto maggiore o uguale a 18 (ignorando quelli senza voto) per ogni materia;

    Onestamente mi viene più difficile lavorare con i filtri...
  • Re: Aiuto per query dove il WHERE è un'altra query

    fratac ha scritto:


    Tra parentesi anche le relazioni non mi convincono. Vedo solo relazioni uno a molti, che complicano le query. Applicando la 3 forma normale sarebbe tutto più semplice. Access con le wizard è semplice per tutti, ma crea buchi enormi nella conoscenza base dei database.
    Errori che poi ci si porta dietro anche quando si padroneggia access.
    Qual'è secondo te una relazione "uno a molti" che non va bene, magari provo a spiegarti la logica che c'è dietro.

    Grazie.
  • Re: Aiuto per query dove il WHERE è un'altra query

    fratac ha scritto:


    Non vorrei dire una baggianata, ma mi sembra di capire che la relazione tra allievi corsi e voto è molti ad uno. Quindi otterrai sempre il primo risultato. Che nel caso di un esame superato in seconda battuta sarà la ricerca ti darà sempre bocciato.
    Questo perché, se non ho sbagliato ragionamento, hai 2 superchiavi diverse che puntano solo al primo voto ottenuto dello studente, che in caso di bocciatura è minore di 17 e non considera il secondo voto positivo.
    Se cosi fosse non avrai solo problemi con questa query, ma con tutte quelle che usano voto come discriminazione.
    Dici bene, è impostata uno a molti perchè nella tabella VotiAllievi ci sono più record con lo stesso IDAllievoCorsi della tabella AllieviCorsi.
    Così, correggimi se sbaglio, se l'allievo pippo ha 3 insufficienze su 3 esami diversi e quindi sulla tabella VotiAllievi ci saranno 3 record con quel IDAllievoCorsi ma relativi a 3 materie differenti, io nella query le vedrò tutte.
    Sbaglio?

    fratac ha scritto:


    Poi, perché hai diviso il voto mettendolo in una tabella diversa?
    Voto a mio avviso deve essere un campo contenuto in tabella con esame, perché devi avere un voto collegato ad ogni esame, in modo che in caso di ripetizione dell esame, avrai due record diversi con due risultati diversi e sopratutto con una superchiave univoca.
    Perché, in teoria la query fa il suo dovere. Ti discrimina i promossi ed i bocciati, ma non quelli in seconda battuta, perché non hai nulla di univoco che certifichi la promozione.
    Quando strutturai il database (ormai diversi anni fa) ritenni opportuno creare una tabella che contiene tutti i voti di tutti gli allievi e di tutti gli esami.
    Ogni record "voto" è collegato a una chieve esterna della tabella AllieviCorsi e a una chiave esterna della tabella EsamiVerbali.
    In questo modo ho comunque l'univocità del voto dell'allievo "pippo" per la materia "informatica".
    Magari questa logica è discutibile e ci saranno tante altre soluzioni migliori comunque "funziona" e comunque ormai il database è stato strutturato così.
  • Re: Aiuto per query dove il WHERE è un'altra query

    maxs84 ha scritto:


    fratac ha scritto:


    Non vorrei dire una baggianata, ma mi sembra di capire che la relazione tra allievi corsi e voto è molti ad uno. Quindi otterrai sempre il primo risultato. Che nel caso di un esame superato in seconda battuta sarà la ricerca ti darà sempre bocciato.
    Questo perché, se non ho sbagliato ragionamento, hai 2 superchiavi diverse che puntano solo al primo voto ottenuto dello studente, che in caso di bocciatura è minore di 17 e non considera il secondo voto positivo.
    Se cosi fosse non avrai solo problemi con questa query, ma con tutte quelle che usano voto come discriminazione.
    Dici bene, è impostata uno a molti perchè nella tabella VotiAllievi ci sono più record con lo stesso IDAllievoCorsi della tabella AllieviCorsi.
    Così, correggimi se sbaglio, se l'allievo pippo ha 3 insufficienze su 3 esami diversi e quindi sulla tabella VotiAllievi ci saranno 3 record con quel IDAllievoCorsi ma relativi a 3 materie differenti, io nella query le vedrò tutte.
    Sbaglio?


    In questo modo ho comunque l'univocità del voto dell'allievo "pippo" per la materia "informatica".
    Magari questa logica è discutibile e ci saranno tante altre soluzioni migliori comunque "funziona" e comunque ormai il database è stato strutturato così.
    NON MODIFICARE LA STRUTTURA O LE RELAZIONI, altrimenti potresti corrompere per sempre il database.
    Se fino ad ora ha "Funzionato" bisogna metterci delle pezze.
    Per me deve essere una relazione molti a molti, visto che lo stesso esame può essere ripetuto infinite volte con infiniti voti.

    ora tu hai un voto collegato ad infiniti corsi.
    Forse mi sbaglio ma secondo me ora tu hai.

    I numeri tra la parentesi indicato un ipotetico numero ID, che insieme creano una superchiave per ricavare il valore voto(valore atomico)

    Primo esame
    IDVotiAllievi(1)-- IDAllievoCorsi(1) Voto 17 (valore atomico): Bocciato
    ripete l'esame, avrai di nuovo.
    IDVotiAllievi(1)-- IDAllievoCorsi(1) Voto 30 (valore atomico): Promosso.

    Considerando che la relazione tra votiallievi e allievicorsi è uno a molti con join sinistro (e quindi ricavi tutti i corsi, ma solo i voti allievi che sono uguali) se non mi sono sbagliato nel ragionamento, hai una super chiave identica per due voti diversi.

    Fino a quando lo stato è bocciato o promosso il problema non sorge.

    Quando invece ti ritrovi con due voti dello stesso studente sullo stesso corso, ti ritrovi nella condizione di avere la stessa chiave ed in teoria, la query riporta solo il primo valore che trova. Che è bocciato.

    Quindi non è che il database funziona bene. E' la prima volta che ti sei accorto dell'errore.

    Quindi, quale era la domanda iniziale che hai posto?
Devi accedere o registrarti per scrivere nel forum
38 risposte