Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 18
  1. #1
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    442

    [MySQL] Query senza HAVING

    Dato lo schema:
    UTENTE(Codice, Nome, Cognome, Età)
    TEATRO(Nome, Città, Capienza)
    ABBONAMENTO(ID, CodUtente, NomeTeatro, Costo)
    Con vincoli di integrità referenziale:
    ABBONAMENTO.CodUtente->UTENTE.Codice
    ABBONAMENTO.NomeTeatro->TEATRO.Nome

    Scrivere in SQL la query che determina: la città con maggior numero di abbonamenti sottoscritti da utenti con fascia d'età compresa tra i 18 ed i 25 anni.
    [VINCOLO: Non è possibile utilizzare il costrutto HAVING]

    Mi sto scontrando con questa query da ieri pomeriggio.
    L'unica cosa chiara è che mi servono tutte e 3 le tabelle e che non penso di poter risolvere con un'unica select, sia pure con annidamenti. Forse qui torna utile una vista? Da utente mi serve l'età, da teatro la città, da abbonamento il numero di sottoscrizioni, dopodiché devo trovare il massimo valore. Con questa query mi trovo i teatri e le rispettive città raggruppati per numero di abbonamenti:

    select nometeatro, citta, count(*) as nr
    from teatro join abbonamento on (nome=nometeatro)
    group by nometeatro;

    Ma non sono nemmeno sicura che mi sia utile
    Mi aiutereste, senza però darmi la soluzione? Vorrei sapere che ragionamenti fate quando componente query così complesse. Grazie!

  2. #2
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    539
    per facilitare tutte le select, anche successive, potresti creare una "view"
    codice:
    CREATE OR REPLACE VIEW tabellaunione AS SELECT
     u.Codice
    ,u.Nome
    ,u.Cognome
    ,u.Età
    ,t.Nome as NomeTeatro
    ,t.Città
    ,t.Capienza
    ,a.ID
    ,a.Costo
    FROM UTENTE u, TEATRO t, ABBONAMENTO a
    WHERE a.CodUtente=u.Codice
    AND a.NomeTeatro=t.Nome
    fatto questo, puoi fare select su "tabellaunione"

    tornando al problema specifico, puoi inserire nella select "ORDER BY .... DESC" e "LIMIT 1"
    ovvero il risultato viene ordinato in modo decrescente ed estratto il primo record

    ma forse è un compito per la scuola ?

  3. #3
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    442
    Sì, sto svolgendo un vecchio compito d'esame per l'uni.
    La tua idea non mi convince molto: perché fare una vista portandosi dietro anche dati inutili ai fini del problema? Come ad esempio nome, cognome, capienza, costo...
    Grazie!

  4. #4
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    539
    se guardi al presente, ti sembra che quei dati siano inutili, se guardi al futuro, gli stessi dati potranno servirti per altre select

    considerato che la "view" non duplica i dati, perché limitarsi al presente ?

    la "view" ti facilita la scrittura delle select avendo di fronte una sola tabella

    pensa ad una query che deve fornire l'ordine dei teatri (rank) per "incasso" generato
    (provala è semplicissima con una sola tabella)
    oppure i posti occupati dagli abbonati rispetto al totale


    hai scritto "Con vincoli di integrità referenziale:"
    per cui lascerei da parte le join e farei una select ... from ... where
    cosa che trovi nella mia "view"
    Ultima modifica di marino51; 12-07-2016 a 19:50 Motivo: ortografia

  5. #5
    l'osservazione di Jiamie04 è corretta: se sei in cerca di performance, non passare per le view

  6. #6
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    539
    Quote Originariamente inviata da optime Visualizza il messaggio
    l'osservazione di Jiamie04 è corretta: se sei in cerca di performance, non passare per le view
    è evidente che abbiamo esperienze diverse

  7. #7
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    539
    non hai reso pubblico il risultato del tuo esercizio, ed a causa della tua perplessità,
    ho pensato di dedicare qualche decina di minuti per illustrarti come "rendere facile la vita con le view" applicate al tuo esercizio

    usando la notazione di mssql

    ho creato UTENTE con 610 record, TEATRO con 30 record e ABBONAMENTO con 610 * 30 / 2 = 9150 record (con uno script php e un po' di "rand")

    ho creato la view
    Codice PHP:
    CREATE VIEW tabellaunione AS SELECT 
     
    [u_codice]        // chiave primaria della tabella utente
    ,[u_nome]
    ,[
    u_cognome]
    ,[
    u_eta]
    ,[
    t_nome]          // chiave primaria della tabella teatro
    ,[t_citta]
    ,[
    t_capienza]
    ,[
    a_id]
    ,[
    a_codutente]     // foreign key che lega l'utente
    ,[a_nometeatro]    // foreign key che lega il teatro
    ,[a_costo]
    FROM utenteteatroabbonamento 
    WHERE a_codutente
    =u_codice AND a_nometeatro=t_nome 
    ho scritto la select per contare il totale degli abbonamenti (9150)
    Codice PHP:
    select sum(x.abbonamenti)
    from (
    select t_cittacount(*) as abbonamenti 
    from tabellaunione 
    group by t_citta

    ho scritto la select per contare gli abbonamenti per città, nella fascia d'età, ottenendone la lista ordinata
    Codice PHP:
    select t_cittacount(*) as abbonamenti 
    from tabellaunione 
    where u_eta between 18 
    and 25 
    group by t_citta
    order by count
    (*) desct_citta 
    ho calcolato la graduatoria applicata alla select precedente
    Codice PHP:
    select x.t_cittax.abbonamenti,
    RANK() OVER ORDER BY x.abbonamenti DESC RankRes
    from
    (
    select t_cittacount(*) as abbonamenti 
    from tabellaunione 
    where u_eta between 18 
    and 25 
    group by t_citta

    ho selezionato le città prime in classifica
    Codice PHP:
    select y.*
    from
    (
    select x.t_cittax.abbonamenti,
    RANK() OVER ORDER BY x.abbonamenti DESC RankRes
    from
    (
    select t_cittacount(*) as abbonamenti 
    from tabellaunione 
    where u_eta between 18 
    and 25 
    group by t_citta
    x
    y
    where y
    .RankRes 1
    order by y
    .abbonamenti descy.t_citta 
    citta2-2 51 1
    citta3-2 51 1
    citta9-2 51 1
    qualche considerazione,
    le tabelle sono tutte relazionate con colonne indicizzate (in questo caso, ma dovrebbero esserlo sempre)
    se non fossero indicizzate, si rischia la lettura sequenziale, con tempi biblici, sia con semplici select, sia con select...join, sia con view

    nel caso in esame se "confronti bene", tutti i tipi di selezione citati, sono applicabili allo stesso modo
    con gli stessi tempi di "elaborazione", essendo, i tipi citati, identici
    (il pc con oltre 9 anni di onorato servizio, quindi non un ultimo grido, ha sempre indicato 00:00:00 come tempo di esecuzione, pur facendolo ripartire prima di ogni query)

    il primo pensiero che avevo cercato di passarti é stato "guarda al futuro" sempre
    il secondo che ti passo ora, tieni le "cose" nella forma più semplice possibile, aiuta molto

    un ultimo pensiero per @optime, il tuo post era decisamente fuori tema e, visto che non lo hai ancora fatto, per favore rileggi il post iniziale e invia il tuo suggerimento,
    quali ragionamenti fai per gestire "query così complesse" ?

    spero di non aver annoiato nessuno
    saluti

  8. #8
    Quote Originariamente inviata da marino51 Visualizza il messaggio
    un ultimo pensiero per @optime, il tuo post era decisamente fuori tema e, visto che non lo hai ancora fatto, per favore rileggi il post iniziale e invia il tuo suggerimento,
    quali ragionamenti fai per gestire "query così complesse" ?
    perché, queste sono query complesse?

    SELECT TOP 1
    T.Citta, COUNT(A.ID)
    FROM
    ABBONAMENTO A
    INNER JOIN UTENTE U ON U.Codice=A.CodUtente AND U.Eta>=18 AND U.Eta<=25
    INNER JOIN TEATRO T ON T.Nome=A.NomeTeatro
    GROUP BY
    T.Citta
    ORDER BY
    COUNT(A.ID) DESC

    tieni presente che per MySQL devi usare LIMIT e non TOP


  9. #9
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    539
    perché, queste sono query complesse?
    sei ancora fuori tema, la discussione non è mia

    ed anche la soluzione non è appropriata se esistono dei "pari merito"

    at salut

  10. #10
    Quote Originariamente inviata da marino51 Visualizza il messaggio
    sei ancora fuori tema, la discussione non è mia

    ed anche la soluzione non è appropriata se esistono dei "pari merito"

    at salut
    scusa, ma che problemi hai? in tema, fuori tema, cosa vuoi che ti dica? se la domanda è (cito da Jamie04): "Vorrei sapere che ragionamenti fate quando componente query così complesse", la risposta "non sono query complesse" è appropriata, per cui, senza fare giri e rigiri, stando semplicemente con i piedi per terra, si studia un po' di SQL e si risolve. E per dimostrare che NON è una query complessa, ho scritto quelle due righe che mi sono venute in mente al volo.

    Per me discussione chiusa

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.