+ Rispondi al Thread
Visualizzazione dei risultati da 1 a 8 su 8

Discussione: SELECT per SQL SERVER migliorabile?

  1. #1
    Fedeciprova non è in linea Scolaretto
    Luogo
    Mantova
    Post
    83

    SELECT per SQL SERVER migliorabile?

    Buongiorno a tutti
    la seguente query di selezione funziona correttamente ma mi sembra poco corretta
    codice:
    Select 
    A.ID, A.CF, A.Cognome, A.Nome, A.DataNascita, A.LuogoNascita, A.Cittadinanza, A.Istruzione, 
    B.ResidenzaVia, B.ResidenzaComune, B.ResidenzaProvincia, B.ResidenzaCAP, B.Telefono, 
    (select top (1) DataInizio FROM sedeMaestranzeAssunzioni ORDER By ID desc) aS Inizio,
    (select top (1) DataFine FROM sedeMaestranzeAssunzioni ORDER By ID desc) as Fine,
    (select top (1) Livello FROM sedeMaestranzeAssunzioni ORDER By ID desc) as Livello,
    (select top (1) Categoria FROM sedeMaestranzeAssunzioni ORDER By ID desc) as Categoria,
    (select top (1) CdCAssunzione FROM sedeMaestranzeAssunzioni ORDER By ID desc) as CdC,
    (select top (1) DataInterruzioneRapporto FROM sedeMaestranzeAssunzioni ORDER By ID desc) as Interruzione,
    (select top (1) TipoAssunzione FROM sedeMaestranzeAssunzioni ORDER By ID desc)as Tipo
    FROM sedeMaestranze AS A LEFT JOIN sedeMaestranzeAnagrafica AS B ON A.ID = B.IDCF 
    LEFT JOIN sedeMaestranzeAssunzioni AS C ON A.ID = C.IDCF WHERE A.CF = 'XYZWQT55A20R123A'
    C'è un altro modo per ottenere lo stesso risultato? Grazie.


    BUON ANNO A TUTTI!!!!!

  2. #2
    L'avatar di AntonioG
    AntonioG non è in linea Moderatore Globale Ultimo blog: Commodore 64 e Codemotion
    Luogo
    Roma
    Post
    16,158
    Blogs
    5
    Ma qual è lo scopo della query? Quali i dati di partenza e quali quelli voluti?
    Avvisi generali e importanti, a pena CHIUSURA thread e/o BAN
    Il crossposting è vietato.
    Le richieste di "pappa pronta" sono vietate.
    Utilizzate i tag CODE per il codice.
    Leggere il Regolamento per chiarimenti PRIMA di creare nuovi thread.
    Utilizzare sempre i PM per comunicare con i moderatori.
    Non mi contattate in PM per problemi di software, usate il forum

  3. #3
    Fedeciprova non è in linea Scolaretto
    Luogo
    Mantova
    Post
    83
    Quote Originariamente inviato da AntonioG Visualizza il messaggio
    Ma qual è lo scopo della query? Quali i dati di partenza e quali quelli voluti?
    Ciao Antonio
    lo scopo è quello di avere un record composto da dati derivanti da tre tabelle:
    nella prima ci sono i dati anagrafici dei soggetti (sedeMaestranze), nella seconda i dati di residenza (sedeMaestranzeAnagrafica) e nella terza i dati di assunzione (sedeMaestranzeAssunzioni).
    Vorrei ricavare i dati della prima tabella con i relativi dati della seconda e (visto che ogni soggetto potrebbe avere più assunzioni) solo i dati con "ID" (integer) più alto della terza tabella.
    L'unico modo che ho trovato per fare funzionare la query è stato quello di separare ogni campo con della terza tabella con "select top ….".
    In realtà la query postata in precedenza non funziona correttamente, mancava un "where" per ogni campo, qui sotto quella che ho ricorretto:
    codice:
    Select 
    A.ID, A.CF, A.Cognome, A.Nome, A.DataNascita, A.LuogoNascita, A.Cittadinanza, A.Istruzione, 
    B.ResidenzaVia, B.ResidenzaComune, B.ResidenzaProvincia, B.ResidenzaCAP, B.Telefono, 
    (select top (1) DataInizio FROM sedeMaestranzeAssunzioni WHERE IDCF = A.ID ORDER By ID desc) aS Inizio,
    (select top (1) DataFine FROM sedeMaestranzeAssunzioni where idcf = A.ID ORDER By ID desc) as Fine,
    (select top (1) Livello FROM sedeMaestranzeAssunzioni where idcf = A.ID ORDER By ID desc) as Livello,
    (select top (1) Categoria FROM sedeMaestranzeAssunzioni where idcf = A.ID ORDER By ID desc) as Categoria,
    (select top (1) CdCAssunzione FROM sedeMaestranzeAssunzioni where idcf = A.ID ORDER By ID desc) as CdC,
    (select top (1) DataInterruzioneRapporto FROM sedeMaestranzeAssunzioni where idcf = A.ID ORDER By ID desc) as Interruzione,
    (select top (1) TipoAssunzione FROM sedeMaestranzeAssunzioni where idcf = A.ID ORDER By ID desc) as Tipo
    FROM sedeMaestranze AS A LEFT JOIN sedeMaestranzeAnagrafica AS B ON A.ID = B.IDCF 
    LEFT JOIN sedeMaestranzeAssunzioni AS C ON A.ID = C.IDCF WHERE A.CF = 'XYZWQT55A20R123A'
    Spero di essere riuscito a spiegarmi

    Grazie

  4. #4
    L'avatar di nman
    nman non è in linea Scribacchino
    Luogo
    Milano
    Post
    1,649
    Andiamo per gradi (Visto che siamo a fine anno mi dilungo .....)

    Parto dal presupposto che nella tabella B ([sedeMaestranzeAnagrafica]) la chiave primaria sia il campo [IDCF] e che quindi hai una relazione 1 a 1 con la tabella A ([sedeMaestranze])

    Alla fine tu selezioni un solo dipendente interessato con il CodiceFiscale
    Devi sapere che la nostra Amministrazione non è riuscita neanche a darci un codice fiscale univoco .... ....
    sembra quasi che lo fanno apposta a fare queste minchiate (perdonatemi l'espressione)

    Poi tu per selezionare l'ultimo record relativo a un dipendente ti affidi al massimo numero di ID ....
    certamente un progressivo e in teoria funziona,
    ma nei DB reali ti potresti ritrovare in seguito a correzioni o altro un record successivo con un ID precedente
    Valuta se non sia meglio usare la [sedeMaestranzeAssunzioni.DataInizio] al posto dell ID
    ... certo è meno performante, ma sei certo che la ultima data di assunzione e l'ultima


    ed ora veniamo alla vista:
    Un primo miglioramento (meglio dire correzione) devi farlo eliminando la 3° tabella (....LEFT JOIN sedeMaestranzeAssunzioni AS C....) dal JOIN
    Tu filtri gia correttamente per ogni record della 3° tabella
    se poi la lasci anche nel JOIN ottieni solo di moltiplicare i record .......
    quindi:
    codice:
    SELECT A.ID, A.CF, A.Cognome, A.eccetera, B.ResidenzaVia, B.ResidenzaComune, B.eccetera, 
    (SELECT TOP (1) C1.DataInizio FROM dbo.sedeMaestranzeAssunzioni AS C1 WHERE (C1.IDCF = A.ID) ORDER BY ID DESC) AS Inizio,
    (SELECT TOP (1) C2.DataFine   FROM dbo.sedeMaestranzeAssunzioni AS C2 WHERE (C2.IDCF = A.ID) ORDER BY ID DESC) AS Fine,
    (SELECT TOP (1) C3.Livello    FROM dbo.sedeMaestranzeAssunzioni AS C3 WHERE (C3.IDCF = A.ID) ORDER BY ID DESC) AS Livello,
    (eccetera ..................................) AS xxxx
    FROM         
    dbo.sedeMaestranze AS A 
    LEFT OUTER JOIN
    dbo.sedeMaestranzeAnagrafica AS B 
    ON A.ID = B.IDCF
    WHERE (A.CF = 'XYZWQT55A20R123A')
    ;

    ma secondo me sarebbe meglio evitare una sottoquery per ogni record bensi fare una unica sottoquery per la 3° tabella nel suo complesso
    codice:
    SELECT A.ID, A.CF, A.Cognome, A.eccetera, B.ResidenzaVia, B.ResidenzaComune, B.Eccetera, C.DataInizio, C.DataFine, C.Livello, C.eccetera
    
    FROM  
           
    	dbo.sedeMaestranze AS A 
    
    LEFT OUTER JOIN
    	dbo.sedeMaestranzeAnagrafica AS B 
    ON A.ID = B.IDCF 
    
    INNER JOIN
    	(
    	SELECT X.IDCF, X.DataInizio, X.DataFine, X.Livello, X.eccetera
    	FROM dbo.sedeMaestranzeAssunzioni AS X
    	WHERE (X.DataInizio = (SELECT MAX(Y.DataInizio) AS MaxDataIni FROM dbo.sedeMaestranzeAssunzioni AS Y WHERE (X.IDCF = Y.IDCF)))
    	) AS C 
    ON A.ID = C.IDCF
    
    
    WHERE (A.CF = 'XYZWQT55A20R123A')
    
    ;
    .
    Ultima modifica di nman; 31-12-2018 07:22 

  5. #5
    L'avatar di gibra
    gibra non è in linea Amanuense
    Luogo
    Breganze (VI)
    Post
    6,048
    Quote Originariamente inviato da Fedeciprova Visualizza il messaggio
    C'è un altro modo per ottenere lo stesso risultato? Grazie.
    Hai già i JOIN tra le tabelle, quei SELECT TOP 1 sono inutili.
    Dovresti sostituirli tutti con il solo campo interessato, ovvero:
    codice:
    SELECT A.ID, A.CF, A.Cognome, A.Nome, A.DataNascita, A.LuogoNascita, A.Cittadinanza, A.Istruzione, 
    B.ResidenzaVia, B.ResidenzaComune, B.ResidenzaProvincia, B.ResidenzaCAP, B.Telefono, 
    DataInizio , DataFine, ecc.

  6. #6
    Fedeciprova non è in linea Scolaretto
    Luogo
    Mantova
    Post
    83
    Eccomi qui

    rispondendo a nman per ovviare al problema "che la nostra Amministrazione non è riuscita neanche a darci un codice fiscale univoco" ho messo come chiave primaria il codice fiscale nella tabella "sedeMaestranze" nella quale c'è un campo "ID" (integer) che incremento da codice, nelle altre tabelle c'è un campo "IDCF"(integer) in cui inserisco il dato da codice, potrebbe sembrare una cavolata ma questo mi permette eventuali correzioni successive al codice fiscale senza compromettere le altre tabelle (almeno spero).
    Ora provo il tuo suggerimento "fare una unica sottoquery per la 3° tabella" anche se avevo già provato ma mi dava solo il primo campo della sottoquery (sicuramente la query era scritta errata).

    Per rispondere a gibra la tua soluzione è stata la prima che avevo fatto ma mi restituiva tante volte il soggetto quanti erano i suoi record nella 3° tabella, anche se, visto il tuo suggerimento, mi viene il dubbio di avere scritto male anche quella query.


    Per cui ora provo tutti i vostri suggerimenti ed a breve vi faccio sapere il risultato.


    Un ringraziamento infinito per le vostre risposte.

  7. #7
    Fedeciprova non è in linea Scolaretto
    Luogo
    Mantova
    Post
    83

    risolto

    Quanto sono ignorante
    Anche oggi ne ho imparata una nuova, non sapevo si potesse fare una select anche per i JOIN…

    ecco la query
    codice:
    SELECT A.ID, A.CF, A.Cognome, A.Nome, A.DataNascita, A.LuogoNascita, A.Cittadinanza, A.Istruzione,
    B.ResidenzaVia, B.ResidenzaComune, B.ResidenzaProvincia, B.ResidenzaCAP, B.Telefono,
    C.DataInizio, C.DataFine, C.Livello, C.Categoria, c.CdCAssunzione, C.DataInterruzioneRapporto, C.TipoAssunzione
    FROM dbo.sedeMaestranze AS A LEFT OUTER JOIN dbo.sedeMaestranzeAnagrafica AS B ON A.ID = B.IDCF 
    INNER JOIN (SELECT X.IDCF, X.Categoria, X.DataInizio, X.DataFine, X.DataInterruzioneRapporto, X.Livello, X.CdCAssunzione, X.TipoAssunzione FROM dbo.sedeMaestranzeAssunzioni AS X 
    WHERE (X.DataInizio = (SELECT MAX(Y.DataInizio) AS MaxDataIni FROM dbo.sedeMaestranzeAssunzioni AS Y
    WHERE (X.IDCF = Y.IDCF)))) AS C ON A.ID = C.IDCF WHERE (A.CF = '" & miavariabile & "'
    Quando scrivo le query io non metto mai "dbo." per i riferimenti delle tabelle e nei JOIN LEFT e RIGHT non scrivo "OUTER", è un errore grave?
    Se si perché?

    Vi ringrazio molto dell'aiuto, auguro a tutto il forum una buona fine anno con l'augurio di un nuovo anno migliore di questo, ci sentiamo l'anno prossimo.
    Ciaooooo .

  8. #8
    L'avatar di nman
    nman non è in linea Scribacchino
    Luogo
    Milano
    Post
    1,649
    Quote Originariamente inviato da Fedeciprova Visualizza il messaggio
    ...... è un errore grave? ......
    Non è grave, ma se si vuole migliorare .......

    Io quando scrivo le query anche se mi sentirei sicuro apro comunque SSMS e la metto in una View
    dopo il salvataggio il tuo testo viene "tradotto" nel dialetto specifico di SQLServer .....

    poi la indento e riordino, --- solo a quel punto la considero finita

    .

+ Rispondi al Thread

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi