2016-06-09 13 views
7

Ho bisogno di aiuto per recuperare record dal database con qualche condizione come spiego qui di seguito: -bisogno per recuperare record per ogni mese di MYSQL

ho bisogno di controllare la disponibilità degli studenti per ogni mese tra il selezionato startDate e la fine Data .

Tabella Struttura: -

enter image description here

dati Tabella: -

enter image description here

Esempio: -

Qui si può prendere la capacità di classe come 20 studenti, per esempio.

Desidero verificare la disponibilità del posto dal 02/2016 al 04/2017.

uscita sarà:

02/2016 - 20 
03/2016 - 19 
04/2016 - 18 
05/2016 - 15 
06/2016 - 20 
. 
. 
. 
02/2017 - 14 
03/2017 - 20 
04/2017 - 18 

grazie in anticipo per l'aiuto.

+0

come potrebbe '05/2016 - 15'? ci sono solo tre voci mostrate negli screenshot –

+0

questo è solo un esempio @kamalpal –

risposta

7

Ho trovato la tua domanda come questa se ci sono numero di studenti e possono iscriversi in qualsiasi momento nel mese questo non è considerato, ma sì, se puoi decidere che sarà comparabile con una data come startDate o endDate questa query sarà sicuramente di aiuto tu.

SELECT count(*) as cnt,CONCAT(MONTH(startDate),'/', YEAR(startDate)) as day from notes group by day 

Ho considerato con startDate.

Per favore fatemi sapere se ho bisogno di ulteriori ricerche.

khajaamin

+0

Sì Aiuterà un po ', ma dov'è il record dell'altro mese? –

+0

ad esempio non ho inserito il 05/2016, quindi restituirà 0 per quel mese. –

+0

puoi aiutarmi per quello? @khajaamin –

2

È necessario utilizzare domanda secondaria o di auto si uniscono per ottenere i risultati richiesti, vedi esempio qui sotto:

SELECT LEFT(startDate,7) startMY, LEFT(endDate,7) endMY, (
    SELECT 20 - COUNT(*) FROM `tablename` B 
    WHERE LEFT(A.startDate,7) >= LEFT(B.startDate,7) AND 
      LEFT(A.endDate,7) <= LEFT(B.endDate,7) 
) balanceCapacity FROM `tablename` A 
GROUP BY LEFT(A.startDate,7), LEFT(A.endDate,7) 

uscita (sulla base di record mostrato in figura):

+---------+---------+-----------------+ 
| startMY | endMY | balanceCapacity | 
+---------+---------+-----------------+ 
| 2015-12 | 2017-07 |    19 | 
| 2016-03 | 2017-04 |    18 | 
| 2016-05 | 2017-03 |    17 | 
+---------+---------+-----------------+ 
+0

grazie per provare a risolvere la mia domanda ... –

+0

Ma con la tua risposta non puoi ottenere il risultato per il mese che non ha record. –

+0

@HarshSanghani Non penso che mysql recuperi le date che non esistono nella tabella del database, ma puoi facilmente controllare la data nell'elenco se non esiste 'balanceCapacity = 20' –

1

Sembra che ci siano alcune persone qui con soluzioni che ti daranno risultati per mesi che non sono completamente gratuiti (se sono completamente gratuiti, nessuna riga viene restituita).

Una buona soluzione sarebbe quella di restituire i numeri occupati per ogni mese, quindi nel codice creare un elenco di mesi nell'intervallo che interessa e sottrarre i risultati della query dall'impostazione predefinita del mese "completamente gratuita" valore.

Ma, se è davvero importante farlo in MySQL per qualche motivo, non c'è un modo generale per dire "dammi un elenco di valori entro un determinato intervallo", ma se non sei contrario a costruire un elenco dei mesi che ti interessano prima di eseguire la query, probabilmente lo si può fare con una grande dichiarazione dell'Unione ed una sinistra unirsi, ad esempio:

SELECT Year, Month, {maxfree} - COUNT(whatever) FROM (
SELECT 2016 AS Year, 1 AS Month 
UNION 
SELECT 2016 AS Year, 2 AS Month 
UNION 
... 
etc 
... 
) AS MonthList 
LEFT JOIN TableName 
    ON YEAR(TableName.whatever) = MonthList.Year 
    AND MONTH(TableName.whatever) = MonthList.Month 
GROUP BY Year, Month 

ecc .. di cui sopra dovranno essere pesantemente modificato per correggere colonna ambiguo nomi ecc. e aggiungi la logica in modo che tutti gli appuntamenti degli studenti a cavallo di un determinato anno e mese siano inclusi nei conteggi e conti correttamente le cose ...le altre risposte lo fanno già, non mi preoccuperò di rifarlo :)

Solo un pensiero su un possibile approccio, quanto sopra non è inteso per essere preso direttamente come risposta.

1

Per questa domanda è stata creata una piccola demo.

In base alle vostre screenshot di database enter image description here enter image description here

schema Esempio tavolo, di dati e di query

create table `test` (
`id` int(11), 
`schoolid` int(11), 
`classroomid` int(11), 
`studentname` varchar(40), 
`startmonth` int(2) unsigned zerofill, 
`startyear` year, 
`endmonth` int(2) unsigned zerofill, 
`endyear` year); 

insert into `test` (
`id`, 
`schoolid`, 
`classroomid`, 
`studentname`, 
`startmonth`, 
`startyear`, 
`endmonth`, 
`endyear`) values (1,1,1,'ccc',3,2016,4,2017), 
(2,1,2,'bbb',05,2016,3,2017), 
(3,1,2,'aaa',12,2016,7,2017), 
(4,1,2,'bbb',05,2016,3,2017), 
(5,1,1,'bbb',09,2016,2,2017), 
(6,1,2,'bbb',06,2016,4,2017), 
(7,1,3,'bbb',03,2016,3,2017), 
(8,1,3,'bbb',01,2016,1,2017), 
(9,1,3,'bbb',11,2016,5,2017); 

Questa query ti porterà i posti rimanenti disponibili in ogni classe, sulla base di month e year coppie.

select `classroomid`,'02' as `start_month`,'2016'`start_year`,'04'`end_month`,'2017'`end_year`,(20-count(`id`)) as `seats_left_in_class` from `test` where `startmonth`>=2 and `startyear`=2016 and `endmonth`<=4 and `endyear`=2017 group by `classroomid` order by `classroomid`; 

È possibile controllare i risultati di esempio in SQL Fiddle

+0

grazie a @peter per la tua demo ... –

1

Si dovrebbe usare PHP per ottenere il conteggio per ogni mese della gamma, SQL da solo non restituirà i dati necessari (facilmente).

Utilizzare SQL per restituire un set di risultati contenente tutti gli studenti avviati prima dell'intervallo O terminato dopo l'intervallo.

Assumendo che il campo di ricerca inizia con $fromDate e finisce con $toDate:

SELECT startDate, endDate 
FROM tableName 
WHERE classroomID = $classroomID AND (
    (startDate BETWEEN $fromDate AND $toDate) OR 
    (endDate BETWEEN $fromDate AND $toDate) OR 
    (startDate < $fromDate AND endDate > $toDate) 
) 

Quindi utilizzare PHP per determinare il numero di posti a sedere sono state prese nel corso di ogni mese di vostra gamma.

In pratica, passa attraverso ogni mese dell'intervallo e conta tutti gli studenti iscritti ao prima di quel mese E la cui iscrizione non era terminata prima di quel mese.

seguito, sto popolando un array chiamato $enrollmentByMonth che conterrà il conteggio del numero di studenti memorizzati da [year][month] e poi semplicemente sottraendo dalla capacità della camera e memorizzazione in $openSeats[year][month]

Supponendo $result è un serie di righe restituite dal database:

$year =  date('Y', $fromDate); 
$month = date('m', $fromDate); 
$endYear = date('Y', $toDate); 
$endMonth = date('m', $toDate); 

$enrollmentByMonth = Array(); 
$openSeats = Array(); 

// loop through each month in range 
while ($year <= $endYear){ 
    while ($year != $endYear || $month <= $endMonth){ 

     $loopDate = mktime(0, 0, 0, $month, 1, $year); // (hr,min,sec,mon,day,year) 

     // loop through each db result row to tally up how 
     // many students enrolled for every month/year combo 
     foreach($result as $row){ 
      $rowStartDate = strtotime($row['startDate']); 
      $rowEndDate = strtotime($row['endDate']); 

      // if student registered prior to loopDate AND student 
      // is still registered as of loopDate THEN count it 
      if($rowStartDate <= $loopDate && $rowEndDate >= $loopDate){     
       $enrollmentByMonth[$year][$month]++; 
      } 
     } 

     $openSeats[$year][$month] = $roomCapacity - $enrollmentByMonth[$year][$month]; 

     $month++; 

     if($month > 12){ 
      $month=1; 
      $year++; 
     } 
    } 
} 

dopo questo ciclo, per la stampa le informazioni desiderato è cosa da poco:

// print out data in the desired format 
foreach($openSeats as $year=>$months){ 
    foreach($months as $month=>$openSeatsThisMonth){ 
     echo "$month/$year - $openSeatsThisMonth<br>"; 
    } 
} 

Scusate, non ho tempo di testarlo, quindi potrebbe esserci un errore di battitura o qualcosa che ho trascurato, ma spero che questo vi metta in una buona direzione ..!