sql >> Database teknologi >  >> RDS >> Mysql

Returner en rangering fra flere tabeller med mySQL

Jeg foreslår, at vi bygger forespørgslen trinvist, trin for trin. Bekræft, at forespørgselsresultaterne er, som vi forventer på hvert trin. Når noget "ikke virker", tag backup af et trin.

Vi ønsker at returnere tre rækker, en for hver række i ___Segmentations , for et specifikt hotelid

 VÆLG r.seg_id , r.seg_text FRA ___Segmentations r HVOR r.seg_hotelid =:hotel_id BESTILLE EFTER r.seg_id 

Tilføj den ydre forbindelse til __Bookings

 VÆLG r.seg_id , r.seg_text , b.boo_id FROM ___Segmentations r LEFT JOIN ___Bookings b PÅ b.boo_segmentation =r.seg_id HVOR r.seg_hotelid =:hotel_id ORDER BY r.boid_ 

Tilføj den ydre joinforbindelse til ___BillableDatas

VÆLG r.seg_id , r.seg_text , b.boo_id , d.bil_id FRA ___Segmentations r LEFT JOIN ___Bookings b PÅ b.boo_segmentation =r.seg_id LEFT JOIN `___BillableDatas` b._d ON d. boo_id HVOR r.seg_hotelid =:hotel_id BESTIL EFTER r.seg_id , b.boo_id , d.bil_id

Hvis det er de rækker, vi er interesserede i, kan vi arbejde på aggregering.

VÆLG r.seg_id , r.seg_text , COUNT(DISTINCT b.boo_id) AS cnt_bookings , COUNT(DISTINCT d.bil_id) AS cnt_billable FROM ___Segmentations r LEFT JOIN ___Bookings b ON b.booFTs segmentation ON b.booFTs JOIN `___BillableDatas` d PÅ d.bil_bookingid =b.boo_id HVOR r.seg_hotelid =:hotel_id GROUP BY r.seg_id , r.seg_text BESTILLE BY r.seg_text

Nu for at få aggregeringen med "total".

Den tilgang, jeg ville tage, ville være at lave "kopier" af rækkerne ved at bruge en CROSS JOIN-operation. Vi kan sammenføje de rækker, der returneres af den allerførste forespørgsel, vi skrev, refereret til som en inline-visning. (Aliaseret som q nedenfor.)

Hvis vi har et komplet sæt rækker, gentaget for hver seg_id/seg_text (den første forespørgsel, vi skrev), kan vi bruge betinget aggregering.

Den sidste forespørgsel, vi skrev (lige ovenfor), er en indlejret visning i forespørgslen nedenfor, kaldet c .

SUM af cnt_bookings fra alle rækkerne er totalen.

For de individuelle optællinger kan vi kun inkludere de rækker, der har et matchende seg_id , i alt den delmængde.

 VÆLG q.seg_id , q.seg_text , SUM(IF(c.seg_id=q.seg_id,c.cnt_bookings,0)) AS cnt_bookings , SUM(c.cnt_bookings) AS tot_bookings , SUM(IF( c.seg_id=q.seg_id,c.cnt_billable,0)) AS cnt_billable , SUM(c.cnt_billable) AS tot_billable FROM ( SELECT t.seg_id , t.seg_text FROM ___Segmentations t WHERE t.seg_DER BY_1 =.thotel_hotelid_1 seg_id ) q CROSS JOIN ( VÆLG r.seg_id , COUNT(DISTINCT b.boo_id) AS cnt_bookings , COUNT(DISTINCT d.bil_id) AS cnt_billable FROM ___Segmentations r LEFT JOIN ___Bookings b.boo_id. d PÅ d.bil_bookingid =b.boo_id HVOR r.seg_hotelid =:hotel_id GRUPPER EFTER r.seg_id ) c GRUPPER EFTER q.seg_id , q.seg_text BESTILLING AF q.seg_text 

I SELECT liste, kan vi foretage opdelingen for at få procentdelen:cnt_bookings * 100.0 / tot_bookings

f.eks.

 VÆLG q.seg_id , q.seg_text , SUM(IF(c.seg_id=q.seg_id,c.cnt_bookings,0)) AS cnt_bookings , SUM(c.cnt_bookings) AS tot_bookings , SUM(IF( c.seg_id=q.seg_id,c.cnt_bookings,0)) * 100,0 / SUM(c.cnt_bookings) AS pct_bookings , SUM(IF(c.seg_id=q.seg_id,c.cnt_billable,0)) AS cnt_billable , SUM (c.cnt_billable) AS tot_billable , SUM(IF(c.seg_id=q.seg_id,c.cnt_billable,0)) * 100,0 / SUM(c.cnt_billable) AS pct_billable 

Rediger ORDER BY-sætningen for at returnere rækkerne i den rækkefølge, du ønsker

Fjern fra SELECT liste de udtryk, der returnerer tot_bookings og tot_billable .

REDIGER

Jeg tror, ​​jeg gik glip af datokriteriet. Vi kan lave de ydre sammenføjninger til indre sammenføjninger og erstatte CROSS JOIN med en LEFT JOIN. Vi har potentiale til at returnere NULL-værdier for cnt_bookings og cnt_billable , kan vi indpakke dem i IFNULL()- eller COALESCE()-funktionen for at erstatte NULL med nul.

 VÆLG q.seg_id , q.seg_text , SUM(IF(c.seg_id=q.seg_id,c.cnt_bookings,0)) AS cnt_bookings , SUM(c.cnt_bookings) AS tot_bookings , SUM(IF( c.seg_id=q.seg_id,c.cnt_bookings,0)) * 100,0 / SUM(c.cnt_bookings) AS pct_bookings , SUM(IF(c.seg_id=q.seg_id,c.cnt_billable,0)) AS cnt_billable , SUM (c.cnt_billable) AS tot_billable , SUM(IF(c.seg_id=q.seg_id,c.cnt_billable,0)) * 100.0 / SUM(c.cnt_billable) AS pct_billable FROM ( SELECT t.seg_id , t.seg_Segmentations ROM t HVOR t.seg_hotelid =:hotel_id_1 BESTILLE EFTER t.seg_id ) q LEFT JOIN ( VÆLG r.seg_id , COUNT(DISTINCT b.boo_id) AS cnt_bookings , COUNT(DISTINCT d.bil_id) AS cnt_billableegmentations __JOIN. .boo_segmentation =r.seg_id JOIN ` ___BillableDatas` d PÅ d.bil_bookingid =b.boo_id OG d.bil_date MELLEM '2017-02-21' OG '2017-02-28' HVOR r.seg_hotelid =:hotel_id GROUP BY r.seg_id ) c ON 1=1 GROUP AF q.seg_id , q.seg_text BESTIL EFTER q.seg_text 


  1. Flere måder at slette dubletter fra SQL-tabeller på

  2. Inverteret SQL SELECT - Find personale, der ikke lavede kolde opkald mellem et datointerval

  3. Hvilken datatype for breddegrad og længdegrad?

  4. Vis SQL-forespørgselsresultater i php