2016-06-05 9 views
5

Prima che qualcuno chieda, sì, questo fa parte di un compito a casa, tuttavia, ho provato e cercato soluzioni simili ma nessuna ha funzionato.Come selezionare l'intera tupla che ha il valore MAX da una sottoquery?

Inoltre, è importante notare che questo deve essere eseguito su un server MySQL, pertanto è necessario prendere in considerazione qualsiasi sintassi specifica da essi.

Per questo, avrete bisogno di quattro tabelle:

person (idperson INT, firstName VARCHAR(45)) 
beer (idbeer INT, name VARCHAR(45)) 
purchase(idpurchase INT, idperson INT) 
beerxpurchase(idpurchase INT, idbeer INT, quantity INT) 

Dove ciascuno dei primi colonne è la chiave primaria tranne beerxpurchase, che è una chiave composta dalla prima e seconda colonna, e tutto il altre colonne che condividono nomi rappresentano una chiave esterna.

Alla fine, ho bisogno di fare una query che restituisca ogni singola persona con l'id della birra che hanno comprato di più in tutti i loro acquisti, e la quantità totale di quel tipo di birra che hanno comprato.

Una query come la seguente:

SELECT person.firstName NAME, beerxpurchase.idBeer BEER, SUM(beerxpurchase.quantity) TOTAL 
FROM person 

INNER JOIN purchase 
on person.idperson = purchase.idperson 

INNER JOIN beerxpurchase 
ON beerxpurchase.idpurchase = purchase.idpurchase 

GROUP BY person.firstName, beerxpurchase.idbeer; 

restituirà l'importo totale delle birre acquistate per ogni codice di birra specifica a persona, qualcosa di simile:

NAME BEER TOTAL 
A  1  5 
A  2  23 
A  3  3 
A  4  19 
A  5  7 
B  1  11 
B  2  3 
B  3  3 
B  4  4 
B  5  5 
C  3  5 
D  1  8 
D  2  4 
D  4  1 
D  5  10 
E  1  9 
E  4  10 

Questo è quello che io considero un buon inizio, tuttavia, da quella query dovrei solo ottenere la tupla che ha la quantità massima per utente. Suona come un GROUP BY NAME, però, in esecuzione qualcosa come:

SELECT preferenence.FIRST_NAME, preferenence.ID_BEER, MAX(preferenence.TOTAL_BOUGHT) FROM 
(
    SELECT person.firstName FIRST_NAME, beerxpurchase.idBeer ID_BEER, SUM(beerxpurchase.quantity) TOTAL_BOUGHT 
    FROM person 

    INNER JOIN purchase 
    on person.idperson = purchase.idperson 

    INNER JOIN beerxpurchase 
    ON beerxpurchase.idpurchase = purchase.idpurchase 

    GROUP BY person.firstName, beerxpurchase.idbeer 
) preferenence 

GROUP BY preferenence.FIRST_NAME 
ORDER BY MAX(preferenence.TOTAL_BOUGHT) DESC; 

perderà l'ID birra corretta, ma manterrà il nome corretto persona e la quantità totale di birre comprato, qualcosa di simile:

FIRST_NAME  ID_BEER  TOTAL_BOUGHT 
A    1   23 
B    1   11 
D    1   10 
E    1   10 
C    3   5 

Da quanto ho letto, la maggior parte dei DBMS non tiene traccia di ID_BEER perché non fa parte del GRUPPO (per quanto ho capito). Tuttavia, la modifica dell'ultimo GROUP su GROUP BY preference.FIRST_NAME, preference.ID_BEER restituirà le stesse tuple dalla sottoquery interna.

Quindi la domanda è: da quella sottoquery, come si procederebbe per ottenere l'intera tupla associata a quello specifico valore massimo? O nel caso in cui sia possibile proporre una soluzione migliore per la sottoquery o la query in generale, è più che benvenuto.

Tutto ciò che non è completamente chiaro o se avete bisogno di ulteriori informazioni sui tavoli e le loro relazioni, per favore fatemelo sapere.

risposta

1
SELECT p.firstName 
    , b.name beer 
    , m.total 
    FROM 
    (SELECT o.idperson 
      , bo.idbeer 
      , SUM(bo.quantity) total 
     FROM beerxpurchase bo 
     JOIN purchase o 
      ON o.idpurchase = bo.idpurchase 
     GROUP 
      BY o.idperson 
      , bo.idbeer 
    ) m 
    JOIN 
    (SELECT idperson 
      , MAX(total) total 
     FROM 
      (SELECT o.idperson 
        , bo.idbeer 
        , SUM(bo.quantity) total 
       FROM beerxpurchase bo 
       JOIN purchase o 
        ON o.idpurchase = bo.idpurchase 
       GROUP 
        BY o.idperson 
        , bo.idbeer 
      ) x 
     GROUP 
      BY idperson 
    ) n 
    ON n.idperson = m.idperson 
    AND n.total = m.total 
    JOIN person p 
    ON p.idperson = m.idperson 
    JOIN beer b 
    ON b.idbeer = m.idbeer 

http://sqlfiddle.com/#!9/c6bb9/15

So che non hai chiesto il nome della birra, ma personalmente tendo a ordinare birra per nome anziché id.

+0

Questo è in uno stile simile alla risposta di @Mahedi Sabuj, in quanto utilizza un join della stessa sottoquery, no? A parte questo, anche il tuo sta funzionando, e hai persino incluso il nome della birra, che gentilezza da parte tua. – Vicyorus

+0

Sì, vedo ora che l'altra risposta ha appena avuto alcuni errori, anche se, direi che il mio è più leggibile ;-) – Strawberry

+0

Non sentirò niente contro di me. – Vicyorus

1

Per ottenere risultati beer_id che è la birra più acquistato da una persona, è necessario seguire questa procedura: -

  1. trovare il numero totale di birra di ogni categoria acquistata da una persona (che è già stato fatto)
  2. trovare il numero massimo di birra da quelli categoria da una persona (solo non conta beer_id)
  3. registrazione & risultato 1 di 2 di con conte & persona

Nota: Qui, raggruppo con idperson perché una persona diversa può avere lo stesso firstName.

Qui è pieno di risposta: -

SELECT person.firstname, personBeer.idbeer, personPurchase.TOTAL_BOUGHT 
FROM 
(
    SELECT purchaseInfo.idperson, MAX(purchaseInfo.TOTAL_BOUGHT) TOTAL_BOUGHT 
    FROM 
    (
     SELECT purchase.idperson, beerxpurchase.idbeer, 
      SUM(beerxpurchase.quantity) TOTAL_BOUGHT 
     FROM purchase 
     INNER JOIN beerxpurchase ON beerxpurchase.idpurchase = purchase.idpurchase 
     GROUP by purchase.idperson, beerxpurchase.idbeer 
    ) purchaseInfo 
    GROUP BY purchaseInfo.idperson 
) personPurchase 
INNER JOIN person ON person.idperson = personPurchase.idperson 
INNER JOIN 
(
    SELECT purchase.idperson, beerxpurchase.idbeer, 
     SUM(beerxpurchase.quantity) TOTAL_BOUGHT 
    FROM purchase 
    INNER JOIN beerxpurchase ON beerxpurchase.idpurchase = purchase.idpurchase 
    GROUP by purchase.idperson, beerxpurchase.idbeer 
) personBeer 
ON personBeer.TOTAL_BOUGHT = personPurchase.TOTAL_BOUGHT 
    AND personBeer.idperson = person.idperson 
ORDER BY personPurchase.TOTAL_BOUGHT DESC 

Spero che ti aiuta.

+1

Ecco una query duplicata, possiamo gestirla con 'CTE' su' SQL Server'. Siccome 'CTE' non supporta' MySQL', quindi usiamo 'sub-query' o stesso' sub-query' più volte (cioè due volte qui) che rende la query grande. –

+0

Controlla l'ortografia per "acquisto", e credo che le query interne debbano utilizzare "acquisto" anziché "persona". Altrimenti, questo è d'oro! Continuerò a provarlo, ma sembra che faccia il lavoro. – Vicyorus