Determinazione data

di pierpippo il
76 risposte

76 Risposte - Pagina 4

  • Comunque se lanci la query calendario dal 1/1/27 al 1/1/27 ti spunta "capodanno"

    Il senso era di evitare codice inutile di if nidificate 

    Per arrivare ad estate passi tutte le condizioni e alla fine è un giorno feriale quando con una interrogazione al db ti ritorna il tipo di giorno.

  • Ok, grazie mille per la delucidazione.

    Quindi elseif serve a ottenere la valutazione della condizione che contiene,

     a condizione però che la prima (if) risultata "false".

    In pratica la condizione if, se vera,  esegue la valorizzazione di  una variabile in questo caso $orario_in_vigore.

    Le condizioni successive valorizzano (sovrascrivono) la stessa variabile se vengono eventualmente eseguite.

    Quindi serve elseif perchè se la prima if è vera la valutazione deve fermarsi alla prima if e ignorare il resto. 

    Usando invece solo if anche nelle seguenti condizioni, esse sarebbero autonome e la loro valutazione andrebbe avanti rischiando la sovrascrittura del valore della variabile che devo ottenere.

    Ora mi si è accesa una "lampadina" leggendo quanto vado ora a citare:

    29/07/2026 - sihsandrea ha scritto:

    da questa data che hai imposto fai quello che serve senza usare curdate

    $sql = "
    UPDATE gbgar_festivita
    SET data = STR_TO_DATE(
            CONCAT(:anno,'-',MONTH(data),'-',DAY(data)),
            '%Y-%m-%d'
    )
    WHERE tipo='fisso'
    ";
    
    $stmt = $pdo->prepare($sql);
    
    $stmt->execute([
        ':anno' => $anno
    ]);

    Mi avevi scritto questo perché avevo pensato al problemino relativo all'aggiornamento anticipato delle date festive rispetto alla primo giorno del nuovo anno. E questo me lo hai suggerito per ovviare usando date imposte invece di "CURDATE."

    Infatti io ho risistemato il form e aggiunto una input apposita ma oggi mi viene in mente questo:

    Partendo dalla tabella esistente con le date festive già compilate per l'anno in corso:

    MariaDB [gbgarage_test]> SELECT * FROM gbgar_festivita;
    +----------+-----------------------+------------+-----------+
    | ID_FESTA | FESTIVITA             | GIORNO     | TIPO      |
    +----------+-----------------------+------------+-----------+
    |        1 | capodanno             | 2026-01-01 | fisso     |
    |        2 | epifania              | 2026-01-06 | fisso     |
    |        3 | liberazione           | 2026-04-25 | fisso     |
    |        4 | lavoratori            | 2026-05-01 | fisso     |
    |        5 | repubblica            | 2026-06-02 | fisso     |
    |        6 | ferragosto            | 2026-08-15 | fisso     |
    |        7 | san francesco         | 2026-10-04 | fisso     |
    |        8 | ogni santi            | 2026-11-01 | fisso     |
    |        9 | immacolata concezione | 2026-12-08 | fisso     |
    |       10 | natale                | 2026-12-25 | fisso     |
    |       11 | santo stefano         | 2026-12-26 | fisso     |
    |       12 | pasqua                | 2026-04-05 | variabile |
    |       13 | pasquetta             | 2026-04-06 | variabile |
    +----------+-----------------------+------------+-----------+
    13 rows in set (0,001 sec)
    

    posso tenerla valida fino al 31/12 e automatizzare la update al primo del nuovo anno con questa query:

    UPDATE gbgar_festivita 
    SET giorno= STR_TO_DATE(CONCAT(YEAR(giorno)+1,'-',MONTH(giorno),'-',DAY(giorno)),'%Y-%m-%d') WHERE tipo='fisso'

    almeno per le date fisse.

    In teoria.  E funziona visto che l'ho provata in console.

    Esiste un modo eventualmente per automatizzare direttamente in sql anche l'aggiornamento delle due date variabili senza usare EASTER di PHP?

    In effetti potrei snellire il mio form che tra una cosa e l'altra è diventato un pochino complesso.

    Mi avevi suggerito già come funziona EASTER ma effettivamente, penso abbia senso usarla partendo da php con la input che detta l'anno da considerare.

    Insomma ho una tabella con record tipo "variabili" e "fissi". Sarebbe inutile un aggiornamento automatico parziale cioè possibile solo per i record con valore tipo="fisso" 

    Ricordo che avevi suggerito che si poteva automatizzare l'aggiornamento di questa tabella affinchè venisse eseguita la query update ad una certa data e orario direttamente creando un event o trigger, non ricordo bene.

    Ma come farebbe mysql o mariadb a calcolare la data pasquale? 

    Sarebbe in ogni caso una cosa che vale la pena fare? Supportata dai server di qualsiasi provider nel caso decidessi poi di implementarla, quando poi migrassi il progetto da localhost all' host del provider (cartella sito + database) ?

    Va beh io per ora mi tengo la soluzione con php che esegue la update a comando ma mi piacerebbe approfondire anche questa opzione.

    Buona serata

    Filippo P.

  • 07/08/2026 - pierpippo ha scritto:

    Ma come farebbe mysql o mariadb a calcolare la data pasquale? 

    Non lo fa, per questo usi PHP per trovare la data.

    07/08/2026 - pierpippo ha scritto:

    posso tenerla valida fino al 31/12 e automatizzare la update al primo del nuovo anno con questa query:

    Questo è un dato fisso. Ogni anno ci saranno.quelle.feste + 1 ad ottobre che non sapevo.

    Quando hai aperto il 3d, volevi usare un Array. Non ha senso impostare da.programma in memoria tutte le.feste, tanto sono sempre quelle, le.metti in tabella e le richiami al bisogno. Tra queste cino pasqua e.pasquetta che sono date variabili.

    Crei il tuo elenco feste in qualsiasi momento (un calendario lo prepari con largo anticipo non il primo.dell'anno). Passi l'anno e aggiorni i dati (o li aggiungi in coda).

    Ricavi pasqua e.psquetta per quella data e lanci il calendario dal al.

    può essere giornaliero (dal 20/03/26 al 20/0326) settimanale., mensile annuale questo lo stabilisce chi carica i dati.

    La query calendario per ogni giorno dal al ti riporta il tipo di giorno così da evitare if invernale if. Scolastico ecc...

    Dagli input data dal e data al passi le date e richiami la query da PHP elaquery restituisce data, tipogiorno ecc...

    07/08/2026 - pierpippo ha scritto:

    Supportata dai server di qualsiasi provider nel caso decidessi poi di implementarla, quando poi migrassi il progetto da localhost all' host del provider (cartella sito + database) ?

    Dipende dalle versioni di PHP e dal.db utilizzato.

    Le query, cambiano un po' di sintassi.

    A parte che il programmatore sceglie quale db usare si potrebbe:

    Se database=mysql query = query mysql

    Se database= firebird query=query firebird ecc.. ecc...

  • Buon pomeriggio.

    alla fin fine anche mi rendo conto che il tuo approccio volto a sfruttare maggiormente il server sql, sarebbe senz'altro migliore e performante. Vorrei chiarire che è solo la mia scarsa conoscenza ovviamente non professionale, che mi ha portato ad andare avanti determinando la data servizio attraverso php.

    Vorrei fare il punto.

    Avrei in pratica due tabelle in cui vengono registrati i servizi assegnati a degli autisti:

    serv_master e serv_detail.

    La popolazione di queste avviene attraverso due form.

    Nel primo viene impostata la data in cui va effettuato il servizio e il dato viene memorizzato in $_SESSION affinché possa restare a disposizione per tutti gli inserimenti successivi, relativi allo stesso giorno.

    In occasione dei cambi di stagione (anno scolastico ) e anno solare, questo stesso form ha dei campi aggiuntivi che restano nascosti in base ad una imput "radiobutton", che servono ad aggiornare eventualmente la tabella delle festività e quella dei periodi dell'anno in base ai quali sono in vigore diversi orari relativi alle corse dei bus di linea.

    Le due tabelle serv_master e serv_detail servono da base dati e anche da archivio. E' da esse infatti che vengono ricavati i dati per mostrare agli autisti quali servizi devono svolgere:

    quindi ho una view generale che mostra i dati prelevati con la select che preleva tutti i campi e che mostra quindi i servizi attribuiti a tutti gli autisti con un intervallo va da due gg avanti, e indietro di un mesetto rispetto la data corrente.

    e ho una view per autista dove vengono prelevati i dati relativi a 2 gg dopo la data corrente.

    Ogni autista vede cosi i propri servizi e non quelli degli altri, ed è interessato a vedere i servizi per il giorno dopo o tuttalpiù due giorni avanti. (poi magari gli inserirò un form "search" per vedersi i servizi che ha fatto nell'ultimo periodo, ma questo al momento non è essenziale).

    queste sono le due tabelle serv_master e detail

    MariaDB [gbgarage_test]> DESCRIBE gbgar_serv_master;
    +-----------+----------------------------------------------------+------+-----+---------+----------------+
    | Field     | Type                                               | Null | Key | Default | Extra          |
    +-----------+----------------------------------------------------+------+-----+---------+----------------+
    | ID_MASTER | int(5)                                             | NO   | PRI | NULL    | auto_increment |
    | AUTISTA   | varchar(30)                                        | YES  |     | NULL    |                |
    | STATO     | enum('operativo','riposo','ferie','indisponibile') | YES  |     | NULL    |                |
    | DATA      | date                                               | YES  |     | NULL    |                |
    | NOTE      | varchar(255)                                       | YES  |     | NULL    |                |
    +-----------+----------------------------------------------------+------+-----+---------+----------------+
    5 rows in set (0,001 sec)
    
    MariaDB [gbgarage_test]> DESCRIBE gbgar_serv_detail;
    +---------------------+--------------------------------------+------+-----+---------+----------------+
    | Field               | Type                                 | Null | Key | Default | Extra          |
    +---------------------+--------------------------------------+------+-----+---------+----------------+
    | ID                  | int(5)                               | NO   | PRI | NULL    | auto_increment |
    | ID_MASTER           | int(5)                               | YES  | MUL | NULL    |                |
    | TIPOLOGIA           | enum('tpl','noleggio','officina','') | YES  |     | NULL    |                |
    | MACCHINA            | varchar(20)                          | YES  |     | NULL    |                |
    | SERVIZI_DA_SVOLGERE | varchar(255)                         | YES  |     | NULL    |                |
    | ID_CORSA            | int(5)                               | YES  | MUL | NULL    |                |
    +---------------------+--------------------------------------+------+-----+---------+----------------+
    6 rows in set (0,001 sec)

    la tabella detail è collegata ovviamente alla tabella master col campi id_master ma anche alla tabella "corse" col campo id_corse.

    la tabella corse è cosi composta:

    DESCRIBE gbgar_corse;
    +--------------+-------------+------+-----+---------+----------------+
    | Field        | Type        | Null | Key | Default | Extra          |
    +--------------+-------------+------+-----+---------+----------------+
    | ID_CORSA     | int(3)      | NO   | PRI | NULL    | auto_increment |
    | ID_TM        | int(3)      | YES  | MUL | NULL    |                |
    | LINEA        | varchar(50) | YES  |     | NULL    |                |
    | PARTENZA     | int(5)      | YES  | MUL | NULL    |                |
    | ORARIO_CORSA | time        | YES  |     | NULL    |                |
    | ARRIVO       | int(5)      | YES  | MUL | NULL    |                |
    | FINE_CORSA   | time        | YES  |     | NULL    |                |
    | KM           | float       | YES  |     | NULL    |                |
    +--------------+-------------+------+-----+---------+----------------+
    8 rows in set (0,001 sec)
    

    A sua volta questa è collegata ad altre due tabelle:

    alla tabella tm(tabelle di marcia) e alla tabella fermate: a quest'ultima con due campi. (partenza e fine_corsa)

    la tabella "tabelle_marcia"
    4 rows in set (0,001 sec)
    MariaDB [gbgarage_test]> SELECT * FROM gbgar_tab_marcia;
    +-------+-------------+-----------+-------------+
    | ID_TM | TABELLA     | PERIODO   | FREQUENZA   |
    +-------+-------------+-----------+-------------+
    |     1 | 913 lun-sab | invernale | scolastica  |
    |     2 | 912 lun-sab | invernale | scolastica  |
    |     3 | 919 lun-sab | estivo    | feriale     |
    |     4 | 811         | invernale | giornaliera |
    |     5 | 811         | invernale | scolastica  |
    +-------+-------------+-----------+-------------+
    5 rows in set (0,001 sec)
    
    
    

    Questo perché la tabella delle tabelle di marcia  (scusa il gioco involontario di parole), mi fornisce una selezione delle corse in base all'orario in vigore.

    (qui ti ho messo un estratto e non la struttura perchè appare più chiaro)

    Sono  infatti le tabelle di marcia (TM) ad essere legate al tipo di giorno (invernale, scolastico, festivo etc...) Quindi se una tabella è festiva non conterrà corse che sono solo feriali ma può contenere corse che restano invariate, cioè che non dipendono dalla festività ma solo dal periodo,  e via dicendo.

    ad es: il record con id 4 è la tab 811 invernale e giornaliera:

    in essa c'è la corsa della linea 151 delle 18.30 che va fatta effettuata sempre da settembre a giugno.

    per cui mi tocca avere una ridondanza inevitabile per gestire tutte queste situazioni: in questo caso infatti hi due record con tabella 811.

    Nella tabella corse la corsa delle 18.30 della linea 811 essendo invernale e giornaliera avrà valore 4 nella colonna di collegamento (id_tm), la corsa della linea 151 ma delle 14.00 avrà id_tm= 5 perchè la tabella in cui è compresa è sempre la 811 ma solo scolastica in fatti questa corsa la domenica e festivi non esiste.

    E poi una tabella di marcia può essere assegnata in toto ad un autista ma è raro, di solito sono spezzate.

    Per cui un autista può dover eseguire una corsa della tabella 811 e poi una della tabella 813 .

    Quindi ho dovuto fare una scelta e impostare il form per assegnare le corse e non le tabelle.

    L'altra tabella mi da le ubicazioni delle fermate.

    MariaDB [gbgarage_test]> DESCRIBE gbgar_fermate;
    +------------+------------------------------+------+-----+---------+----------------+
    | Field      | Type                         | Null | Key | Default | Extra          |
    +------------+------------------------------+------+-----+---------+----------------+
    | ID_FERMATA | int(5)                       | NO   | PRI | NULL    | auto_increment |
    | UBICAZIONE | varchar(50)                  | YES  |     | NULL    |                |
    | TIPO       | enum('capolinea','transito') | YES  |     | NULL    |                |
    +------------+------------------------------+------+-----+---------+----------------+
    3 rows in set (0,001 sec)
    

    Questa poi mi tornerà utile per abbinare percorsi e corse e creare un vademecum sui percorsi delle linee. 

    Quindi estraendo i dati da queste tabelle ho ottenuto che ogni servizio assegnato può essere un noleggio e quindi va descritto e amen o una corsa di servizio tpl (linea) ed in questo caso anziché descritto va solo selezionato tra una lista di tutte le corse in carico al vettore. 

    In base al giorno e al periodo questa lista è diversificata.

    ed è qui che entra in gioco il tuo diverso approccio che non riesco però ad adattare. :-(

    Ciliegina sulla torta, nella lista delle corse "papabili" quelle già assegnate per lo stesso giorno, non ricompaiono, cosi non possono erroneamente essere selezionate/assegnate due volte. 

    Anche gli autisti sono elencati in una tabella a se ma questi devono essere sempre tutti disponibili nella select del form con cui i servizi vengono assegnati, perché ad un autista si deve poter assegnare un servizio noleggio e, con un inserimento a se stante, per la stessa data anche una corsa tpl.

    Un pezzetto alla volta, salvo qualche dettaglio che sicuramente va perfezionato, questo era il mio obiettivo.

    Tuttavia, il tuo approccio mi interessa anche solo per il gusto di saperlo:

    In teoria tu dicevi di creare una tabella calendario ma per quanto ci abbia pensato non riesco a capire come potrei adottare il tuo approccio al mio caso.

    In ogni caso grazie per tutto.

    Filippo P.

  • 29/07/2026 - sihsandrea ha scritto:

    da questa data che hai imposto fai quello che serve senza usare curdate

    $sql = "
    UPDATE gbgar_festivita
    SET data = STR_TO_DATE(
            CONCAT(:anno,'-',MONTH(data),'-',DAY(data)),
            '%Y-%m-%d'
    )
    WHERE tipo='fisso'
    ";
    
    $stmt = $pdo->prepare($sql);
    
    $stmt->execute([
        ':anno' => $anno
    ]);

    ciao,

    scusa ma questa query con usando $pdo non funzia e quindi l'ho modificato cosi:

    if(isset ($imposta_feste)){
        $sql="
        UPDATE gbgar_festivita
        SET giorno=
        STR_TO_DATE(
        CONCAT(?,'-',MONTH(giorno),'-',DAY(giorno)),
        '%Y-%m-%d'
        )
        WHERE tipo='fisso'
        ;";
    
        $stmt = $Conn->prepare($sql);
        $stmt->bind_param("s",$anno);
        $stmt->execute();
    
    
        echo"<div class='risposta'>I giorni festivi sono aggiornati per l'anno $anno</div>";
    }

    analogamente stesso criterio per pasqua e pasquetta.

    Credo sia perchè lo script di connessione al database non è impostato su $pdo ma su $Conn.

    Grazie di tutto.

    Filippo P.

  • 20/06/2026 - sihsandrea ha scritto:

    20/06/2026 - pierpippo ha scritto:

    per quanto riguarda la tabella che mi fornisce le date di scadenza del periodo invernale/estivo,

    lo avevo gia previsto.

    se vuoi puoi continuare così, io l'ho ricostruita tramite query usando la stessa struttura di aggiornamento annuale delle date.

    ti mostro la gestione annuale che avevo previsto con le tabelle necessarie per lo sviluppo del calendarioo corse.

    -- create
    CREATE TABLE corse_config (
        id INT AUTO_INCREMENT PRIMARY KEY,
        tipo_giorno VARCHAR(20),
        numero_corse INT
    );
    CREATE TABLE festivita (
        id INT PRIMARY KEY AUTO_INCREMENT,
        nome VARCHAR(255),
        data DATE,
        tipo ENUM('FISSO', 'VARIABILE', 'inizio', 'fine')
    );
    CREATE TABLE calendario_corse (
        id INT AUTO_INCREMENT PRIMARY KEY,
        data_servizio DATE,
        tipo_giorno VARCHAR(20),
        numero_corse INT,
        generato_il TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
    CREATE TABLE corse (
        id INT AUTO_INCREMENT PRIMARY KEY,
        data_servizio DATE,
        numero_corsa INT,
        ora_partenza TIME
    );
    -- insert
    INSERT INTO festivita VALUES (0001, 'CAPODANNO', '2025-01-01', 'FISSO');
    INSERT INTO festivita VALUES (0002, 'EPIFANIA', '2025-01-06', 'FISSO');
    INSERT INTO festivita VALUES (0003, 'LIBERAZIONE', '2025-04-25', 'FISSO');
    INSERT INTO festivita VALUES (0004, 'FESTA DEL LAVORO', '2025-05-01', 'FISSO');
    INSERT INTO festivita VALUES (0005, 'REPUBBLICA', '2025-06-02', 'FISSO');
    INSERT INTO festivita VALUES (0006, 'FERRAGOSTO', '2025-08-15', 'FISSO');
    INSERT INTO festivita VALUES (0007, 'TUTTI I SANTI', '2025-11-01', 'FISSO');
    INSERT INTO festivita VALUES (0008, 'IMMACOLATA', '2025-12-08', 'FISSO');
    INSERT INTO festivita VALUES (0009, 'NATALE', '2025-12-25', 'FISSO');
    INSERT INTO festivita VALUES (0010, 'SANTO STEFANO', '2025-12-26', 'FISSO');
    INSERT INTO festivita VALUES (0011, 'PASQUA', '2025-12-26', 'VARIABILE');
    INSERT INTO festivita VALUES (0012, 'PASQUETTA', '2025-12-26', 'VARIABILE');
    INSERT INTO festivita VALUES (0013, 'scolastico', '2025-01-01', 'inizio');
    INSERT INTO festivita VALUES (0014, 'scolastico', '2025-07-15', 'fine');
    INSERT INTO festivita VALUES (0015, 'scolastico', '2025-09-15', 'inizio');
    INSERT INTO festivita VALUES (0016, 'scolastico', '2025-12-31', 'fine');
    INSERT INTO festivita VALUES (0017, 'estivo', '2025-07-16', 'inizio');
    INSERT INTO festivita VALUES (0018, 'estivo', '2025-09-14', 'fine');  
    INSERT INTO corse_config (tipo_giorno, numero_corse) VALUES
    ('SCOLASTICO', 5),
    ('ESTIVO', 3),
    ('FESTIVO', 2);
    -- fetch 
    
    -------------------------------------------------------------------------
    // questa sarebbe la tua tabella periodi, io l'ho generata da festività
    SELECT
        nome,
        data AS data_inizio,
        (
            SELECT MIN(data)
            FROM festivita f2
            WHERE f2.nome = f1.nome
            AND f2.tipo = 'fine'
            AND f2.data > f1.data
        ) AS data_fine
    FROM festivita f1
    WHERE tipo='inizio';
    
    ----------------------------------------------------------------------
    
    query che genera il calendario 
    WITH RECURSIVE calendario AS (
        SELECT DATE('2025-01-01') AS giorno  /// qui usi il parametro inizio periodo
    
        UNION ALL
    
        SELECT giorno + INTERVAL 1 DAY
        FROM calendario
        WHERE giorno < '2025-12-31'   /// qui usi il parametro fine periodo
        ),
    
        periodi AS (
        SELECT
            f1.nome,
            f1.data AS data_inizio,
            (
                SELECT MIN(f2.data)
                FROM festivita f2
                WHERE f2.nome = f1.nome
                  AND f2.tipo = 'fine'
                  AND f2.data > f1.data
            ) AS data_fine
        FROM festivita f1
        WHERE f1.tipo = 'inizio'
        )
    
    SELECT
        c.giorno,
    
        CASE
    
            WHEN DAYOFWEEK(c.giorno) = 1
                 OR EXISTS (
                    SELECT 1
                    FROM festivita f
                    WHERE f.data = c.giorno
                      AND f.tipo IN ('FISSO','VARIABILE')
                 )
            THEN 'FESTIVO'
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'estivo'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 'ESTIVO'
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'scolastico'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 'SCOLASTICO'
    
            ELSE 'NESSUNO'
    
        END AS servizio,
    
        CASE
    
            WHEN DAYOFWEEK(c.giorno) = 1
                 OR EXISTS (
                    SELECT 1
                    FROM festivita f
                    WHERE f.data = c.giorno
                      AND f.tipo IN ('FISSO','VARIABILE')
                 )
            THEN 2
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'estivo'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 3
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'scolastico'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 5
    
            ELSE 0
    
        END AS numero_corse
    
    FROM calendario c
    ORDER BY c.giorno;
    
    risultati
    
    tabella festività che crei tu
    +----+------------------+------------+-----------+
    | id | nome             | data       | tipo      |
    +----+------------------+------------+-----------+
    |  1 | CAPODANNO        | 2025-01-01 | FISSO     |
    |  2 | EPIFANIA         | 2025-01-06 | FISSO     |
    |  3 | LIBERAZIONE      | 2025-04-25 | FISSO     |
    |  4 | FESTA DEL LAVORO | 2025-05-01 | FISSO     |
    |  5 | REPUBBLICA       | 2025-06-02 | FISSO     |
    |  6 | FERRAGOSTO       | 2025-08-15 | FISSO     |
    |  7 | TUTTI I SANTI    | 2025-11-01 | FISSO     |
    |  8 | IMMACOLATA       | 2025-12-08 | FISSO     |
    |  9 | NATALE           | 2025-12-25 | FISSO     |
    | 10 | SANTO STEFANO    | 2025-12-26 | FISSO     |
    | 11 | PASQUA           | 2025-12-26 | VARIABILE |
    | 12 | PASQUETTA        | 2025-12-26 | VARIABILE |
    | 13 | scolastico       | 2025-01-01 | inizio    |
    | 14 | scolastico       | 2025-07-15 | fine      |
    | 15 | scolastico       | 2025-09-15 | inizio    |
    | 16 | scolastico       | 2025-12-31 | fine      |
    | 17 | estivo           | 2025-07-16 | inizio    |
    | 18 | estivo           | 2025-09-14 | fine      |
    +----+------------------+------------+-----------+
    
    
    tabella configurazione corse che crei tu
    +----+-------------+--------------+
    | id | tipo_giorno | numero_corse |
    +----+-------------+--------------+
    |  1 | SCOLASTICO  |            5 |
    |  2 | ESTIVO      |            3 |
    |  3 | FESTIVO     |            2 |
    +----+-------------+--------------+
    
    
    tabella che mi fornisce le date di scadenza del periodo invernale/estivo
    +------------+-------------+------------+
    | nome       | data_inizio | data_fine  |
    +------------+-------------+------------+
    | scolastico | 2025-01-01  | 2025-07-15 |
    | scolastico | 2025-09-15  | 2025-12-31 |
    | estivo     | 2025-07-16  | 2025-09-14 |
    +------------+-------------+------------+
    
    
    tabella calendario generato in automatico.
    +------------+------------+--------------+
    | giorno     | servizio   | numero_corse |
    +------------+------------+--------------+
    | 2025-01-01 | FESTIVO    |            2 |
    | 2025-01-02 | SCOLASTICO |            5 |
    | 2025-01-03 | SCOLASTICO |            5 |
    | 2025-01-04 | SCOLASTICO |            5 |
    | 2025-01-05 | FESTIVO    |            2 |
    | 2025-01-06 | FESTIVO    |            2 |
    | 2025-01-07 | SCOLASTICO |            5 |
    | 2025-01-08 | SCOLASTICO |            5 |
    | ...        | ...        |          ... |
    | 2025-12-28 | FESTIVO    |            2 |
    | 2025-12-29 | SCOLASTICO |            5 |
    | 2025-12-30 | SCOLASTICO |            5 |
    | 2025-12-31 | SCOLASTICO |            5 |
    +------------+------------+--------------+
    
    

    io l'ho generato annuale ma tu puoi passare i parametri tramite php a mysql.

    considera che fa tutto lato mysql, php passa solo i valori data inizio e data fine del calendario da generare.

    Ciao, e buone ferie in ogni caso,

    Procedendo con il mio progettino mi imbatto sempre a pensare alla metodologia che mi hai suggerito e che ti riporto in  citazione, non riesco a fare meno di voler capire come adattarla al mio scopo.

    Io al momento ho lavorato procedendo attraverso php, creando delle if (come ricorderai forse) che mi portano a caratterizzare la data del servizio e che mi porta ad avere vari parametri riguardo la data_servizio:

     invernale/estiva/natalizio/pasquale per quanto riguarda l'orario in vigore 

    e

    feriale/festivo/scolastico.

    Continuo a pensare di adottare il tuo metodo ma per cortesia, potresti chiarirmi alcune cose?:

    Insomma sto decifrando il tuo codice per capire se e come adattarlo al mio caso, anche se nel frattempo vado avanti per la strada che le mie attuali conoscenza mi permette.

    Quindi:

    WHIT RECURSIVE lavora come un ciclo e UNION ALL mette insieme record di tabelle con campi compatibili e di egual numero in una tabella provvisoria (fa in verticale ciò che le join fanno in orizzontale),  giusto?

    Il mio parametro data_servizio non è un intervallo di date ma una data unica.

    Ma immagino che l' inizio_periodo e il fine_periodo che intendi tu possa essere lo stesso valore per cui il periodo è di un unico giorno nel mio caso.

    Mi pare di capire che il tuo suggerimento porti a creare un calendario che mi dice quante corse vanno effettuate in ogni giorno dell'anno

    Tuttavia a me non serve sapere quante corse, ma quali vanno effettuate in un giorno specifico del calendario che si genera, calendario poi che sarebbe di un giorno solo .

    Per farla breve, insomma mi permetto di incollare qua le tabelle coinvolte, perché quella lunga query che inizia con la funzione WHIT RECURSIVE, sicuramente si può adattare al caso specifico al fine di creare un elenco di corse relative alla data_servizio.

    //tabella gbgar_corse;
    
    MariaDB [gbgarage_test]> SELECT * FROM gbgar_corse;
    +----------+-------+-------+----------+--------------+--------+------------+------+
    | ID_CORSA | ID_TM | LINEA | PARTENZA | ORARIO_CORSA | ARRIVO | FINE_CORSA | KM   |
    +----------+-------+-------+----------+--------------+--------+------------+------+
    |        1 |     1 | L.157 |       16 | 06:40:00     |     15 | 07:50:00   | 40.6 |
    |        2 |     2 | L.157 |       15 | 13:20:00     |     17 | 14:17:00   |   39 |
    |        3 |     2 | L.157 |       14 | 14:37:00     |      8 | 15:50:00   | 56.5 |
    |        4 |     2 | L.159 |        8 | 06:30:00     |     14 | 07:39:00   | 42.8 |
    |        5 |     3 | L.141 |        7 | 05:55:00     |     18 | 06:50:00   | 16.1 |
    |        6 |     4 | L.151 |        8 | 18:30:00     |     19 | 19:22:00   |   31 |
    +----------+-------+-------+----------+--------------+--------+------------+------+
    6 rows in set (0,001 sec)
    
    //struttura gbgar_corse
    +--------------+-------------+------+-----+---------+----------------+
    | Field        | Type        | Null | Key | Default | Extra          |
    +--------------+-------------+------+-----+---------+----------------+
    | ID_CORSA     | int(3)      | NO   | PRI | NULL    | auto_increment |
    | ID_TM        | int(3)      | YES  | MUL | NULL    |                |
    | LINEA        | varchar(50) | YES  |     | NULL    |                |
    | PARTENZA     | int(5)      | YES  | MUL | NULL    |                |
    | ORARIO_CORSA | time        | YES  |     | NULL    |                |
    | ARRIVO       | int(5)      | YES  | MUL | NULL    |                |
    | FINE_CORSA   | time        | YES  |     | NULL    |                |
    | KM           | float       | YES  |     | NULL    |                |
    +--------------+-------------+------+-----+---------+----------------+
    8 rows in set (0,001 sec)
    
    //tabella gbgar_fermate
    +------------+-----------------------+-----------+
    | ID_FERMATA | UBICAZIONE            | TIPO      |
    +------------+-----------------------+-----------+
    |          1 | Ravenna FS            | capolinea |
    |          2 | Ravenna FS box1       | capolinea |
    |          3 | Ravenna FS box2       | capolinea |
    |          4 | Ravenna FS box3       | capolinea |
    |          5 | Ravenna FS Radiotaxi  | capolinea |
    |          6 | RA Maroncelli box1    | capolinea |
    |          7 | RA Maroncelli box2    | capolinea |
    |          8 | RA C.ne Molino        | capolinea |
    |          9 | RA v.le Randi-Cassino | capolinea |
    |         10 | RA Ist agrario        | capolinea |
    |         11 | RA Ist callegari      | capolinea |
    |         12 | RA Fornace Zarattini  | capolinea |
    |         13 | Marina RA Traghetto   | capolinea |
    |         14 | Forlì Punto Bus       | capolinea |
    |         15 | Forlì Centro Studi    | capolinea |
    |         16 | Roncalceci            | capolinea |
    |         17 | Coccolia v.Taverna    | capolinea |
    |         18 | S.Alberto p.zza       | capolinea |
    |         19 | Villa Prati v.chiara  | capolinea |
    +------------+-----------------------+-----------+
    //Questa l'ho creata perchè cmq mi farà comodo per quando dovrò creare la tabella tragitti che a tempo debito metterà in collegamento questa tabella con la tabella corse.
    
    
    //tabella gbgar_tab_marcia
    MariaDB [gbgarage_test]> SELECT * FROM gbgar_tab_marcia;
    +-------+-------------+-----------+-------------+
    | ID_TM | TABELLA     | PERIODO   | FREQUENZA   |
    +-------+-------------+-----------+-------------+
    |     1 | 913 lun-sab | invernale | scolastica  |
    |     2 | 912 lun-sab | invernale | scolastica  |
    |     3 | 919 lun-sab | estivo    | feriale     |
    |     4 | 811         | invernale | giornaliera |
    |     5 | 811         | invernale | scolastica  |
    +-------+-------------+-----------+-------------+
    5 rows in set (0,001 sec)
    
    //struttura gbgar_tab_marcia
    +-----------+------------------------------------------------------+------+-----+---------+----------------+
    | Field     | Type                                                 | Null | Key | Default | Extra          |
    +-----------+------------------------------------------------------+------+-----+---------+----------------+
    | ID_TM     | int(3)                                               | NO   | PRI | NULL    | auto_increment |
    | TABELLA   | varchar(15)                                          | YES  |     | NULL    |                |
    | PERIODO   | enum('invernale','estivo')                           | YES  |     | NULL    |                |
    | FREQUENZA | enum('feriale','scolastica','festiva','giornaliera') | NO   |     | NULL    |                |
    +-----------+------------------------------------------------------+------+-----+---------+----------------+
    4 rows in set (0,001 sec)
    
    //il legame è determinato da id_tm (ogni tabella comprende una serie di corse). Le tabelle hanno la loro periodicità e frequenza per cui le relative corse di conseguenza devono o non devono apparire nell' elenco che vorrei ottenere.
    
    //tabella gbgar_festività (non metto struttura tabella visto che tanto nn ha relazioni)
    MariaDB [gbgarage_test]> SELECT * FROM gbgar_festivita; 
    +----------+-----------------------+------------+-----------+
    | ID_FESTA | FESTIVITA             | GIORNO     | TIPO      |
    +----------+-----------------------+------------+-----------+
    |        1 | capodanno             | 2026-01-01 | fisso     |
    |        2 | epifania              | 2026-01-06 | fisso     |
    |        3 | liberazione           | 2026-04-25 | fisso     |
    |        4 | lavoratori            | 2026-05-01 | fisso     |
    |        5 | repubblica            | 2026-06-02 | fisso     |
    |        6 | ferragosto            | 2026-08-15 | fisso     |
    |        7 | san francesco         | 2026-10-04 | fisso     |
    |        8 | ogni santi            | 2026-11-01 | fisso     |
    |        9 | immacolata concezione | 2026-12-08 | fisso     |
    |       10 | natale                | 2026-12-25 | fisso     |
    |       11 | santo stefano         | 2026-12-26 | fisso     |
    |       12 | pasqua                | 2026-04-05 | variabile |
    |       13 | pasquetta             | 2026-04-06 | variabile |
    +----------+-----------------------+------------+-----------+
    13 rows in set (0,001 sec)
    
    //tabella gbgar_periodi (nn metto la struttura tanto questa nn ha relazioni)
    +------------+---------------------+-------------+------------+
    | id_periodo | descrizione_periodo | data_inizio | data_fine  |
    +------------+---------------------+-------------+------------+
    |          1 | periodo_invernale   | 2026-09-15  | 2027-06-05 |
    |          2 | periodo_estivo      | 2026-06-07  | 2026-09-14 |
    |          3 | periodo_natalizio   | 2026-12-24  | 2027-01-06 |
    |          4 | periodo_pasquale    | 2027-03-25  | 2027-03-30 |
    +------------+---------------------+-------------+------------+
    4 rows in set (0,001 sec)
    

    Non mi resterebbe che seguire il modello citato in testa alla presente, adattandolo alle tabelle che ho riportato, ma se non ho capito male il risultato che cerco è diverso da quello dell' esempio e quindi mi occorre un ennesimo aiuto..... volendo e  potendo ovviamente.

    In ogni caso ringrazio  e saluto.

    Buone ferie.

    Filippo P

  • 19/08/2026 - pierpippo ha scritto:

    WHIT RECURSIVE lavora come un ciclo

    si questa

    WITH RECURSIVE calendario AS (
        SELECT DATE('2026-01-01') AS giorno
    
        UNION ALL
    
        SELECT giorno + INTERVAL 1 DAY
        FROM calendario
        WHERE giorno < '2026-12-31'
    )

    è un ciclo sql ti restituisce

    2026-01-01
    2026-01-02
    2026-01-03
    ...
    2026-12-31

    ovvio che puoi mettere dal al e ottenere un giorno, una settimana, un mese, un periodo.

    probabilmente nel tuo caso non serve proprio il RECURSIVE

    union non è una join...

    se hai due tabelle identiche per struttura puoi unirle (accodare la tabella 2 allla tabella 1 e viceversa).

    non si limita solo a questo...

    supponiamo che hai la tabella:

    id; descrizione; bla bla;
    1   fattura          xxxx
    2  bolla             xxxxx
    3  nota credito  xxxxx

    e la vuoi usare come combobox per filtrare ma vuoi che mostri pure tutti senza filtro fai la union con null

    select * from tipidocumento
    union
    '', '', ''
    order by descrizione

    ottieni

    id; descrizione; bla bla;
    ''    ''             ''
    1   fattura          xxxx
    2  bolla             xxxxx
    3  nota credito      xxxxx

    oppure 

    select id, descrizione from....
    union 
    '', ''

    ottieni la stessa tabella ma senza il campo "bla bla"

    quindi quale sia la tabella origine puoi selezionare n campi e unire n campi

    un altro esempio:

    select id, descrizione from ....
    union 
    0, TUTTI

    ottieni

    id; descrizione;
    0   TUTTI                  
    1   fattura          
    2   bolla             
    3   nota credito  

    problema:

    hai una struttura così:

    gbgar_corse
           |
           | ID_TM
           ?
    gbgar_tab_marcia
    
    gbgar_tab_marcia
    ID_TM | TABELLA | PERIODO | FREQUENZA
    
    //determina quando una tabella marcia è valida.
    
    gbgar_corse
    ID_CORSA | ID_TM | LINEA | ORARIO...
    
    //contiene le corse appartenenti a quella tabella marcia.

    Quindi il ragionamento è:

    DATA_SERVIZIO
          ?
    che giorno della settimana è?
          ?
    è festivo?
          ?
    in quale periodo siamo?
          ?
    quale FREQUENZA è valida?
          ?
    quale PERIODO è valido?
          ?
    quali ID_TM sono compatibili?
          ?
    quali corse appartengono a quegli ID_TM?
          ?
    ELENCO DELLE CORSE DEL GIORNO

    Ed è esattamente qui che il database può fare il lavoro al posto del PHP

    lato php:

    <?php
    
    $data_servizio = '2026-08-24';
    
    $sql = "
    WITH parametri AS (
        SELECT CAST(? AS DATE) AS data_servizio
    ),
    
    periodo AS (
        SELECT
            gp.descrizione_periodo,
    
            CASE gp.descrizione_periodo
                WHEN 'periodo_pasquale'   THEN 'pasquale'
                WHEN 'periodo_natalizio'  THEN 'natalizio'
                WHEN 'periodo_estivo'     THEN 'estivo'
                WHEN 'periodo_invernale'  THEN 'invernale'
            END AS periodo
    
        FROM gbgar_periodi gp
        CROSS JOIN parametri x
    
        WHERE x.data_servizio BETWEEN gp.data_inizio AND gp.data_fine
    
        ORDER BY
            CASE gp.descrizione_periodo
                WHEN 'periodo_pasquale'   THEN 1
                WHEN 'periodo_natalizio'  THEN 2
                WHEN 'periodo_estivo'     THEN 3
                WHEN 'periodo_invernale'  THEN 4
                ELSE 99
            END
    
        LIMIT 1
    ),
    
    giorno AS (
        SELECT
            x.data_servizio,
    
            CASE
    
                WHEN DAYOFWEEK(x.data_servizio) = 1
                  OR EXISTS (
                        SELECT 1
                        FROM gbgar_festivita f
                        WHERE f.GIORNO = x.data_servizio
                    )
                THEN 'festiva'
    
                WHEN DAYOFWEEK(x.data_servizio) = 7
                THEN 'feriale'
    
                ELSE 'scolastica'
    
            END AS frequenza
    
        FROM parametri x
    )
    
    SELECT
        c.ID_CORSA,
        c.ID_TM,
        c.LINEA,
        c.PARTENZA,
        c.ORARIO_CORSA,
        c.ARRIVO,
        c.FINE_CORSA,
        c.KM,
    
        p.periodo,
        g.frequenza
    
    FROM gbgar_corse c
    
    INNER JOIN gbgar_tab_marcia tm
        ON tm.ID_TM = c.ID_TM
    
    CROSS JOIN periodo p
    CROSS JOIN giorno g
    
    WHERE
        tm.PERIODO = p.periodo
    
        AND (
            tm.FREQUENZA = g.frequenza
            OR tm.FREQUENZA = 'giornaliera'
        )
    
    ORDER BY
        c.ORARIO_CORSA
    ";
    
    $stmt = $Conn->prepare($sql);
    
    if (!$stmt) {
        die("Errore prepare: " . $Conn->error);
    }
    
    $stmt->bind_param("s", $data_servizio);
    
    $stmt->execute();
    
    $result = $stmt->get_result();
    
    while ($corsa = $result->fetch_assoc()) {
    
        echo $corsa['ID_CORSA'] . " - "
           . $corsa['LINEA'] . " - "
           . $corsa['ORARIO_CORSA'] . "<br>";
    }
    
    $stmt->close();

    per provare lato mysql

    WITH periodo AS (
        SELECT
            descrizione_periodo,
    
            CASE descrizione_periodo
                WHEN 'periodo_pasquale'   THEN 'pasquale'
                WHEN 'periodo_natalizio'  THEN 'natalizio'
                WHEN 'periodo_estivo'     THEN 'estivo'
                WHEN 'periodo_invernale'  THEN 'invernale'
            END AS periodo
    
        FROM gbgar_periodi
    
        WHERE '2026-08-24' BETWEEN data_inizio AND data_fine
    
        ORDER BY
            CASE descrizione_periodo
                WHEN 'periodo_pasquale'   THEN 1
                WHEN 'periodo_natalizio'  THEN 2
                WHEN 'periodo_estivo'     THEN 3
                WHEN 'periodo_invernale'  THEN 4
                ELSE 99
            END
    
        LIMIT 1
    ),
    
    giorno AS (
        SELECT
            '2026-08-24' AS data_servizio,
    
            CASE
    
                WHEN DAYOFWEEK('2026-08-24') = 1
                  OR EXISTS (
                        SELECT 1
                        FROM gbgar_festivita f
                        WHERE f.GIORNO = '2026-08-24'
                    )
                THEN 'festiva'
    
                WHEN DAYOFWEEK('2026-08-24') = 7
                THEN 'feriale'
    
                ELSE 'scolastica'
    
            END AS frequenza
    )
    
    SELECT
        c.ID_CORSA,
        c.ID_TM,
        c.LINEA,
        c.PARTENZA,
        c.ORARIO_CORSA,
        c.ARRIVO,
        c.FINE_CORSA,
        c.KM,
    
        p.periodo,
        g.frequenza
    
    FROM gbgar_corse c
    
    INNER JOIN gbgar_tab_marcia tm
        ON tm.ID_TM = c.ID_TM
    
    CROSS JOIN periodo p
    CROSS JOIN giorno g
    
    WHERE
        tm.PERIODO = p.periodo
    
        AND (
            tm.FREQUENZA = g.frequenza
            OR tm.FREQUENZA = 'giornaliera'
        )
    
    ORDER BY
        c.ORARIO_CORSA;

    fammi sapere...

    forse si deve rivedere la tabella di configurazione corse tra invernale e scolastico.

  • Interessante!

    Forse inizio a capirci qualcosa, anche se:

    Ho provato lato sql la query e in effetti mi da una tabella vuota:

    Empty set (0,001 sec)

    Se non ho capito male essendoci una corsa in gbgar_corse con id_corsa 5 e id_tm 3, 

    ed essendo che la tabella gbgar_tab_marcia  in  id_tm 3 ha la tabella 919 lun-sab con periodicità estiva e frequenza feriale.

    per la data 2026-08-24 che è un lunedì la tabella per questa data mi doveva restituire 

    id_corsa | id_tm | Linea ....  

    5             |   3     | L.141 .... 

    Insomma qualche cosa da correggere ci sarà ma il senso è questo.

    Mi rende una tabella con la lista delle corse che sono legate a quella data.

    Infatti è bastato sostituire 'giornaliera' con 'feriale' che sql mi ha restituito il record che mi aspettavo. Cioè l'unico presente attualmente nella tabella fisica gbgar_corse che fosse legata ad una tabella di marcia con quella periodicità e frequenza.

    Quindi in sostanza devo aggiungere solo la join per avere il nome della fermata di partenza. Altrimenti mi tira fuori lo sterile id_fermata.

    Prelevare solo i  campi

    Linea, orario_corsa, partenza.

    Visto che devo determinare la lista delle corse che deve apparire nella tendina del form con cui vengono assegnati i servizi;

    e aggiungere la condizione "not exists" per togliere gli id_corsa già presenti in gbgar_serv_detail.

    Con calma appena riesco provo a implementare il tutto.

    e prima di questo onestamente per non scrivere codice a "pappagallo", ho visto che hai inserito delle cross join che non so cosa siano, occorre quindi che me le vada a vedere.

    E anche DAYOFWEEK:

    mi pare di intuire un problemino in relazione alla frequenza:

    infatti scrivi:

    CASE
    
                WHEN DAYOFWEEK('2026-08-24') = 1
                  OR EXISTS (
                        SELECT 1
                        FROM gbgar_festivita f
                        WHERE f.GIORNO = '2026-08-24'
                    )
                THEN 'festiva'
    
                WHEN DAYOFWEEK('2026-08-24') = 7
                THEN 'feriale'
    
                ELSE 'scolastica'
    
            END AS frequenza
    )

    la data è feriale o scolastica a seconda dei periodi: nel periodo estivo, natalizio e pasquale i giorni feriali sono appunto feriali (non scolastici) ma in quello invernale un giorno feriale è scolastico.

    Ma la distinzione è indispensabile perchè è legata alle tabelle di marcia che a loro volta comprendono o meno determinate corse.

    Non so, temo, che questa query non possa distinguere questo fattore.

    Io leggo che se la data =7 (valore qualsiasi  da 2 a 7), restituisce vero e quindi la data è feriale.

    Ma se la stessa data ricade in periodo invernale, e non è festiva, allora invece di feriale va definita scolastica.

    Se ho capito bene quindi, devo rivedere la tabella gbgar_tab_marcia oppure va ridefinita la query? 

    Va bene in ogni caso ti ringrazio sempre tanto e appena sarò riuscito a far funzionare il tutto secondo questo nuovo metodo, ti faccio sapere senz'altro.

    Filippo P.

  • Hai solo un problema di sottoinsiemi.

    Per esempio, in periodo invernale dal... al... hai come sottoinsiemi le domeniche, le feste invernali e i periodi scolastici.

    Per estrapolare le corse per quel tipo di giornata hai due strade percorribili:

    1) impostare un campo priorità e prelevare il primo record (quel limit 1 ti mostra solo il primo record) a seconda della priorità (se le priorità sono da 1 a n e decidi di prendere il valore massimo li ordino per priorità decrescente o viceversa). in questo caso devi portarti dietro un identificativo delle corse che raggruppa quanti mezzi circolano quel giorno (corse ordinarie e scuolabus).

    2) estrarre sia le corse invernali (che suppongo vengano fatte a prescindere) e l'unione dei percorsi scuolabus (o se hanno personale dedicato replicare l'associazione corse - autisti). in pratica lanci la selezione ordinaria con l'elenco delle corse ordinarie e poi quella scolastica (penso da 2 a 4 corse 8:00-14:00 e 14:00-20:00 o come hai previsto le corse scolastiche).

    Quindi la differenza per i periodi scolastici implica l'inserimento nella lista corse le 2 o 4 corse scuolabus.

    Io ho creato le query partendo da un modello che usavo per servizio dialisi e ambulanza dove spesso le corse erano stabilite in giornata (chi ha fatto la dialisi di urgenza notturna non la faceva il giorno stesso e veniva tolto dall'elenco). Quindi ho adattato il modello in base a quanto mi hai detto. la logica è la stessa, puoi avere un mezzo in autorimessa o quel giorno una ordinanza chiude le scuole o altri motivi.

    Fammi sapere come intendi gestire le corse, non i percorsi e le fermate ma i mezzi che in base al giorno indicato devono effettuare il servizio. fatta l'analisi possiamo adattare meglio gli automatismi. Considerando che siamo partiti da una query che deve estrapolare il tipo di giornata, siamo arrivati ad estrapolare i mezzi per quella giornata. sapendo che è feriale, invernale e scolastico la query ti deve fornire l'elenco dei mezzi in servizio non i percorsi che sono una gestione a parte.

    Quindi in base alla data che passi, la query ti mostra quanti e quali mezzi devi associare all'autista. sai che hai 5 mezzi ordinari, 1 scuolabus e, eventualmente, 1 mezzo per gita scolastica (la faccio complicata, lo so).

    il risultato, passando a mysql una data, indicativamente al minimo sindacale, sarà del tipo:

    id|   mezzo o targa   |  descrizione                               |
    1    iveco xc111aa      Palermo stazione c.le - Enna stazione c.le
    --
    n    inbus xx111xx      scuola vattelapesca...
    
    // ogni riferimento è puramente casuale...

    Questi sono i mezzi in circolazione in base al tipo di data.

    Poi di contro associ gli autisti (segue la stessa logica in base a ferie e non) e la disponibilità solo che invece di avere un elenco di mezzi hai un elenco di autisti.

    Selezioni il mezzo, selezioni l'autista e pigi il tasto "associa" e hai registrato corsa con autista nel diario corse (se fossero consegne pensalo come la compilazione di un borderò o bordereau).

    In questo modo fra 2 anni, quando arriva una multa sai chi era alla guida del mezzo.

    chiusa parentesi, questo automatismo, tutto in memoria, serve per avere l'elenco dei mezzi e degli autisti, la registrazione la fai successivamente, infatti sono tutte select nessuna update o insert.

    Successivamente, finita l'assegnazione, puoi modificare il diario in base alle reali esigenze (malattia, sostituzione, mezzo guasto ecc...).

  • Ti rimando il procedimento lato mysql della gestione. per comandare da php adesso sai come si fa.

    -- create
    CREATE TABLE corse_config (
        id INT AUTO_INCREMENT PRIMARY KEY,
        tipo_giorno VARCHAR(20),
        numero_corse INT
    );
    CREATE TABLE festivita (
        id INT PRIMARY KEY AUTO_INCREMENT,
        nome VARCHAR(255),
        data DATE,
        tipo ENUM('FISSO', 'VARIABILE', 'inizio', 'fine')
    );
    CREATE TABLE calendario_corse (
        id INT AUTO_INCREMENT PRIMARY KEY,
        data_servizio DATE,
        tipo_giorno VARCHAR(20),
        numero_corse INT,
        generato_il TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
    CREATE TABLE corse (
        id INT AUTO_INCREMENT PRIMARY KEY,
        data_servizio DATE,
        numero_corsa INT,
        ora_partenza TIME
    );
    -- insert
    // POPOLO LA TABELLA FESTIVITà CON DATI DI ESEMPIO...
    
    INSERT INTO festivita VALUES (0001, 'CAPODANNO', '2025-01-01', 'FISSO');
    INSERT INTO festivita VALUES (0002, 'EPIFANIA', '2025-01-06', 'FISSO');
    INSERT INTO festivita VALUES (0003, 'LIBERAZIONE', '2025-04-25', 'FISSO');
    INSERT INTO festivita VALUES (0004, 'FESTA DEL LAVORO', '2025-05-01', 'FISSO');
    INSERT INTO festivita VALUES (0005, 'REPUBBLICA', '2025-06-02', 'FISSO');
    INSERT INTO festivita VALUES (0006, 'FERRAGOSTO', '2025-08-15', 'FISSO');
    INSERT INTO festivita VALUES (0007, 'TUTTI I SANTI', '2025-11-01', 'FISSO');
    INSERT INTO festivita VALUES (0008, 'IMMACOLATA', '2025-12-08', 'FISSO');
    INSERT INTO festivita VALUES (0009, 'NATALE', '2025-12-25', 'FISSO');
    INSERT INTO festivita VALUES (0010, 'SANTO STEFANO', '2025-12-26', 'FISSO');
    INSERT INTO festivita VALUES (0011, 'PASQUA', '2025-12-26', 'VARIABILE');
    INSERT INTO festivita VALUES (0012, 'PASQUETTA', '2025-12-26', 'VARIABILE');
    INSERT INTO festivita VALUES (0013, 'scolastico', '2025-01-07', 'inizio');
    INSERT INTO festivita VALUES (0014, 'scolastico', '2025-07-15', 'fine');
    INSERT INTO festivita VALUES (0015, 'scolastico', '2025-09-15', 'inizio');
    INSERT INTO festivita VALUES (0016, 'scolastico', '2025-12-24', 'fine');
    INSERT INTO festivita VALUES (0017, 'estivo', '2025-07-16', 'inizio');
    INSERT INTO festivita VALUES (0018, 'estivo', '2025-09-14', 'fine');  
    INSERT INTO festivita VALUES (0019, 'INVERNALE', '2025-01-01', 'inizio');
    INSERT INTO festivita VALUES (0020, 'INVERNALE', '2025-07-31', 'fine');
    INSERT INTO festivita VALUES (0021, 'INVERNALE', '2025-09-01', 'inizio');
    INSERT INTO festivita VALUES (0022, 'INVERNALE', '2025-12-31', 'fine');
    
    // POPOLO LA TABELLA CONFIGURAZIONE CORSE CON DATI DI ESEMPIO
    // I DATI SONO IL PERIODO E IL NUMERO DI MEZZI CHE CIRCOLANO MA PUOI METTERE QUELLO CHE VUOI
    
    INSERT INTO corse_config (tipo_giorno, numero_corse) VALUES
    ('SCOLASTICO', 5),
    ('INVERNALE', 4),
    ('ESTIVO', 3),
    ('FESTIVO', 2);
    
    -- fetch 
    // ESTRAPOLIAMO I DATI IN AUTOMATICO
    // NON SCRIVO NESSUNA TABELLA FISICA
    // SONO DATI IN MEMORIA
    
    SELECT * FROM FESTIVITA;
    
    // MOSTRO COSA HO CARICATO COME FESTIVITà E NON
    +----+------------------+------------+-----------+
    | id | nome             | data       | tipo      |
    +----+------------------+------------+-----------+
    |  1 | CAPODANNO        | 2025-01-01 | FISSO     |
    |  2 | EPIFANIA         | 2025-01-06 | FISSO     |
    |  3 | LIBERAZIONE      | 2025-04-25 | FISSO     |
    |  4 | FESTA DEL LAVORO | 2025-05-01 | FISSO     |
    |  5 | REPUBBLICA       | 2025-06-02 | FISSO     |
    |  6 | FERRAGOSTO       | 2025-08-15 | FISSO     |
    |  7 | TUTTI I SANTI    | 2025-11-01 | FISSO     |
    |  8 | IMMACOLATA       | 2025-12-08 | FISSO     |
    |  9 | NATALE           | 2025-12-25 | FISSO     |
    | 10 | SANTO STEFANO    | 2025-12-26 | FISSO     |
    | 11 | PASQUA           | 2025-12-26 | VARIABILE |
    | 12 | PASQUETTA        | 2025-12-26 | VARIABILE |
    | 13 | scolastico       | 2025-01-07 | inizio    |
    | 14 | scolastico       | 2025-07-15 | fine      |
    | 15 | scolastico       | 2025-09-15 | inizio    |
    | 16 | scolastico       | 2025-12-24 | fine      |
    | 17 | estivo           | 2025-07-16 | inizio    |
    | 18 | estivo           | 2025-09-14 | fine      |
    | 19 | INVERNALE        | 2025-01-01 | inizio    |
    | 20 | INVERNALE        | 2025-07-31 | fine      |
    | 21 | INVERNALE        | 2025-09-01 | inizio    |
    | 22 | INVERNALE        | 2025-12-31 | fine      |
    +----+------------------+------------+-----------+
    
    
    SELECT
        nome AS PERIODO,
        data AS data_inizio,
        (
            SELECT MIN(data)
            FROM festivita f2
            WHERE f2.nome = f1.nome
            AND f2.tipo = 'fine'
            AND f2.data > f1.data
        ) AS data_fine
    FROM festivita f1
    WHERE tipo='inizio';
    // QUESTA MOSTRA I DATI PER COME LI HAI PENSATI IN ORIGINE TU
    
    // RISULTATO: 
    +------------+-------------+------------+
    | PERIODO    | data_inizio | data_fine  |
    +------------+-------------+------------+
    | scolastico | 2025-01-07  | 2025-07-15 |
    | scolastico | 2025-09-15  | 2025-12-24 |
    | estivo     | 2025-07-16  | 2025-09-14 |
    | INVERNALE  | 2025-01-01  | 2025-07-31 |
    | INVERNALE  | 2025-09-01  | 2025-12-31 |
    +------------+-------------+------------+
    
    // ADESSO ABBIAMO VERIFICATO DI AVERE TUTTO QUELLO CHE SERVE PER CREARE IL CALENDARIO 
    
    WITH RECURSIVE calendario AS (
        SELECT DATE('2025-01-01') AS giorno  // DATA DI PARTENZA DELLA QUERY
        UNION ALL
    
        SELECT giorno + INTERVAL 1 DAY // MI SPOSTO LA DATA DI UN GIORNO PERCHè USO MINORE E MAGGIORE        
                                       //SENZA UGUALE
        FROM calendario
        WHERE giorno < '2025-01-31'   //DATA DI ARRIVO DELLA QUERY IN QUESTO CASO TUTTO GENNAIO
        ),
    
        periodi AS (
        SELECT
            f1.nome,
            f1.data AS data_inizio,
            (
                SELECT MIN(f2.data)
                FROM festivita f2
                WHERE f2.nome = f1.nome
                  AND f2.tipo = 'fine'
                  AND f2.data > f1.data
            ) AS data_fine
        FROM festivita f1
        WHERE f1.tipo = 'inizio'
        )
    
    SELECT
        c.giorno,
    
        CASE
    
            WHEN DAYOFWEEK(c.giorno) = 1
                 OR EXISTS (
                    SELECT 1
                    FROM festivita f
                    WHERE f.data = c.giorno
                      AND f.tipo IN ('FISSO','VARIABILE')
                 )
            THEN 'FESTIVO'
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'estivo'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 'ESTIVO'
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'scolastico'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 'SCOLASTICO'
    
            WHEN EXISTS (
              SELECT 1
              FROM periodi p
              WHERE p.nome = 'INVERNALE'
                AND c.giorno BETWEEN p.data_inizio AND p.data_fine
          )
          THEN 'INVERNALE'
    
          ELSE 'NESSUNO'
    
        END AS servizio,
    
        CASE
    
            WHEN DAYOFWEEK(c.giorno) = 1
                 OR EXISTS (
                    SELECT 1
                    FROM festivita f
                    WHERE f.data = c.giorno
                      AND f.tipo IN ('FISSO','VARIABILE')
                 )
            THEN 2
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'estivo'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 3
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'scolastico'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 5
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'INVERNALE'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 4
    
            ELSE 0
    
        END AS numero_corse
    
    FROM calendario c
    ORDER BY c.giorno;
    
    // RISULTATO DAL 01/01/AAAA AL 31/01/AAAA
    
    +------------+------------+--------------+
    | giorno     | servizio   | numero_corse |
    +------------+------------+--------------+
    | 2025-01-01 | FESTIVO    |            2 |
    | 2025-01-02 | INVERNALE  |            4 |
    | 2025-01-03 | INVERNALE  |            4 |
    | 2025-01-04 | INVERNALE  |            4 |
    | 2025-01-05 | FESTIVO    |            2 |
    | 2025-01-06 | FESTIVO    |            2 |
    | 2025-01-07 | SCOLASTICO |            5 |
    | 2025-01-08 | SCOLASTICO |            5 |
    | 2025-01-09 | SCOLASTICO |            5 |
    | 2025-01-10 | SCOLASTICO |            5 |
    | 2025-01-11 | SCOLASTICO |            5 |
    | 2025-01-12 | FESTIVO    |            2 |
    | 2025-01-13 | SCOLASTICO |            5 |
    | 2025-01-14 | SCOLASTICO |            5 |
    | 2025-01-15 | SCOLASTICO |            5 |
    | 2025-01-16 | SCOLASTICO |            5 |
    | 2025-01-17 | SCOLASTICO |            5 |
    | 2025-01-18 | SCOLASTICO |            5 |
    | 2025-01-19 | FESTIVO    |            2 |
    | 2025-01-20 | SCOLASTICO |            5 |
    | 2025-01-21 | SCOLASTICO |            5 |
    | 2025-01-22 | SCOLASTICO |            5 |
    | 2025-01-23 | SCOLASTICO |            5 |
    | 2025-01-24 | SCOLASTICO |            5 |
    | 2025-01-25 | SCOLASTICO |            5 |
    | 2025-01-26 | FESTIVO    |            2 |
    | 2025-01-27 | SCOLASTICO |            5 |
    | 2025-01-28 | SCOLASTICO |            5 |
    | 2025-01-29 | SCOLASTICO |            5 |
    | 2025-01-30 | SCOLASTICO |            5 |
    | 2025-01-31 | SCOLASTICO |            5 |
    +------------+------------+--------------+
    
    A QUESTO PUNTO SAI CHE è SCOLASTICO=INVERNALE E QUANTI MEZZI CIRCOLANO
    N.B. NUMERO CORSE PUOI USARLO COME CONFIGURAZIONE TRA INVERNALE E SCOLASTICO USALO COME VUOI.
    OVVIAMENTE PUOI PASSARE DAL AL COME SINGOLO GIORNO, SETTIMANA, MESE, PERIODO O ANNO...
    FAI LE PROVE LATO MYSQL SENZA I COMMENTI CHE HO INSERITO (I VARI //BLA BLA CHE HO MESSO).
  • 25/08/2026 - sihsandrea ha scritto:

    Fammi sapere come intendi gestire le corse, non i percorsi e le fermate ma i mezzi che in base al giorno indicato devono effettuare il servizio. fatta l'analisi possiamo adattare meglio gli automatismi. Considerando che siamo partiti da una query che deve estrapolare il tipo di giornata, siamo arrivati ad estrapolare i mezzi per quella giornata. sapendo che è feriale, invernale e scolastico la query ti deve fornire l'elenco dei mezzi in servizio non i percorsi che sono una gestione a parte.

    Le corse sono gestite nella tabella gbgar_corse e sono collegate alla tabella gbgar_tab_marcia, che le raggruppa a seconda dell'orario in vigore e della frequenza.

    Ogni tabella di marcia è un insieme di corse che vanno effettuate. 

    Ogni tabella ha una periodicità principale: estiva, invernale.

    All'interno della periodicità invernale in cui è in vigore l'orario invernale, abbiamo un periodo natalizio e pasquale perché il periodo invernale è legato al periodo scolastico che però ha due interruzioni.

    Quindi i giorni feriali invernali sono scolastici tranne che nel periodo natalizio e pasquale.

    Non devo associare nessun mezzo.

    La gestione degli automezzi per ora non la voglio implementare; non ho scuolabus, non mi serve al momento inserire anche la gestione dei mezzi.

    L'archivio delle corse assegnate è dato dalle tabelle gbgar_serv_master e gbgar_serv_detail.

    In esse vengono registrati i servizi assegnati.

    A me serve solamente determinare una lista di corse in base alla data in cui i servizi vanno eseguiti.

    Se la data_servizio è invernale e  non ricade nei periodi natalizio e pasquale, i giorni feriali sono tutti scolastici, i due parametri coincidono in sostanza, tuttavia mi servono entrambi perché una tabella di marcia se contiene corse scolastiche viene definita scolastica, altrimenti anche se il giorno è scolastico, mettiamo il caso che contenga corse pomeridiane/serali, non viene definita scolastica ma feriale perché le corse che comprende non sono di interesse scolastico e infatti trattasi di tabelle che appunto per le corse che comprende va svolta in tutti i giorni invernali e feriali, cioè anche se per dire si tratta del lunedì 28 dicembre in cui le scuole sono chiuse.

    Per corse scolastiche non si intende corse scuolabus. Vengono effettuate con bus normali adibiti al normale servizio di linea. 

    Quindi in sostanza se il giorno è invernale e scolastico ad es. , devo prelevare dalla tabella gbgar_corse tutte le corse che, attraverso il campo id_tm,  sono legate a tabelle di marcia presenti in gbgar_tab_marcia, che hanno:  

    • innanzitutto valore "invernale" nel campo periodo  
    • e poi sia quelle che hanno valore "scolastico"  che quelle che hanno valore  "feriale" nel campo frequenza.

    analogamente se il giorno è invernale e festivo, tipo una domenica, devo prelevare le corse che hanno valori in  id_tm, legate ai record con id_tm della tabella gbgar_tab_marcia che hanno:

    • valore "invernale" nel campo 'periodo' ,
    • valore "festivo" nel campo 'frequenza'.

    Il fatto che ho dovuto creare nella tabella periodi anche il periodo natalizio e pasquale, è che se la data_servizio ricade tra data_inzio  del periodo natalizio e data_fine dello stesso periodo, non devo prelevare le corse legate a tabelle con valore (frequenza='scolastico') ma solo quelle che hanno valore 'feriale'. Le corse di interesse scolastico sono infatti sospese in tutto il periodo natalizio.

    Lo stesso per il periodo pasquale.

    Quindi io tutto quello che vorrei fare è semplificare il file "selezione_corse.php" mettendo una query che seguendo il tuo "approccio" ottiene lo stesso risultato scaricando il lavoro sul server del database, ma alla fine devo ottenere la stessa cosa che ora ottengo con lo script che riporto sotto:

    <?php session_start();?>
    <!DOCTYPE html>
    <html lang="it">
    <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Script per selezione corse</title>
    </head>
    <body>
    <!-- Questo script seleziona la corse che devono apparire nella select del form di gestione dei servizi -->
    
    <?php
    
    
    $periodi_db = [];
    
    $periodi_db = $_SESSION['periodi'];
    $data_servizio = $_SESSION['data'];
    
    //echo $data_servizio ."<br>";
    
    
    // echo"<pre>";
    // print_r ($periodi_db);
    // echo"</pre>";
    
    
    $inizio_invernale = $periodi_db['periodo_invernale']['data_inizio'];
    $fine_invernale = $periodi_db['periodo_invernale']['data_fine'];
    $inizio_estivo = $periodi_db['periodo_estivo']['data_inizio'];
    $fine_estivo = $periodi_db['periodo_estivo']['data_fine'];
    $inizio_natale = $periodi_db['periodo_natalizio']['data_inizio'];
    $fine_natale = $periodi_db['periodo_natalizio']['data_fine'];
    $inizio_pasqua = $periodi_db['periodo_pasquale']['data_inizio'];
    $fine_pasqua = $periodi_db['periodo_pasquale']['data_fine'];
    
    
    
    //DETERMINAZIONE DELLA DATA ORARIO/PERIODO IN VIGORE
    
    if($data_servizio >= $inizio_invernale && $data_servizio<$inizio_natale){
            $orario_in_vigore="invernale";
            //echo $orario_in_vigore;
    }elseif($data_servizio>$fine_natale && $data_servizio<$inizio_pasqua){
            $orario_in_vigore="invernale";
            //echo $orario_in_vigore;
    }elseif($data_servizio>$fine_pasqua && $data_servizio<=$fine_invernale){
            $orario_in_vigore="invernale";
            //echo $orario_in_vigore;
    }elseif($data_servizio>=$inizio_natale && $data_servizio<=$fine_natale){
            $orario_in_vigore="natalizio";
            //echo $orario_in_vigore;
    }elseif($data_servizio>=$inizio_pasqua && $data_servizio<=$fine_pasqua){
            $orario_in_vigore="pasquale";
            //echo $orario_in_vigore;
    }else{$orario_in_vigore="estivo";
            //echo $orario_in_vigore;
    }
    
    
    //DETERMINAZIONE GIORNO FESTIVO
    //estrazione date festive
    $query_festivita="SELECT giorno FROM gbgar_festivita;";
    $result_hday=$Conn->query($query_festivita);
    
    //creazione matrice con le date dei giorni festivi
    $holiday=[];
    while($row=$result_hday->fetch_assoc()){
            $holiday[]=$row['giorno'];
            }
    //print_r($holiday);
    
    // DETERMINAZIONE GIORNO DELLA SETTIMANA
    $dayweek = new DateTime($data_servizio);
    
    //DETERMINAZIONE GIORNI FESTIVI
    if(in_array($data_servizio,$holiday) || $dayweek->format('w')==0){
            $giorno_servizio="festivo";
            //echo "<br>". $giorno_servizio;
    }elseif($dayweek->format('w')>=1 || $dayweek->format('w')<=5){
            $giorno_servizio="feriale";        
    }else{$giorno_servizio="sabato";
            //echo "<br>". $giorno_servizio;
    }
    
    
    
    /*README
    Le condizioni sono impostate affinché la query sulla tabella users deve sempre essere eseguita;
    mentre:
    Le query sulle tabelle che contengono le linee devono essere eseguite sia che la data di riferimento sia o meno impostata, perchè altrimenti il form si blocca mentre
    deve cmq permettere la modifica e la cancellazione delle registrazioni;
    Nel caso sia impostata (!empty($data_grezza)) la data sarà in ogni caso compresa tra uno degli intervalli definiti.
    */
    
    /*i campi relativi a periodi e frequenza sono stati spostati dalla tabella gbgar_corse alla tab gbgar_tab_marcia
    per cui nelle query è stata aggiunta una join per unire le tabelle citate; 
    di conseguenza, le condizioni seguenti, prima della subquery  fanno riferimento alla nuova tabella gbgar_tab_marcia (T)*/
    
    //query relativo a periodo invernale, giorno feriale + sabato
    if($orario_in_vigore==="invernale" && $giorno_servizio==="feriale" || $giorno_servizio==="sabato"){
            $query_corse_sql =
            "SELECT id_corsa,linea,gbgar_fermate.ubicazione as partenza,DATE_FORMAT(orario_corsa,'%H:%i') AS orario_corsa
            FROM gbgar_corse C
            JOIN gbgar_fermate 
            ON C.partenza=gbgar_fermate.id_fermata
            JOIN gbgar_tab_marcia T
            ON C.id_tm = T.id_tm
            WHERE T.periodo='invernale'
            AND T.frequenza IN('scolastica','giornaliera')
            AND NOT EXISTS(
            SELECT 1 FROM gbgar_serv_master M
            JOIN gbgar_serv_detail D ON M.id_master=D.id_master
            WHERE D.id_corsa=C.id_corsa
            AND M.data='$data_servizio');";
            $corse_da_svolgere = $Conn->query($query_corse_sql);
    }//query relativo a periodo invernale, giorno festivo
    if($orario_in_vigore==="invernale" && $giorno_servizio==="festivo"){
            $query_corse_sql =
            "SELECT id_corsa,linea,gbgar_fermate.ubicazione as partenza,DATE_FORMAT(orario_corsa,'%H:%i') AS orario_corsa
            FROM gbgar_corse C
            JOIN gbgar_fermate 
            ON C.partenza=gbgar_fermate.id_fermata
            JOIN gbgar_tab_marcia T
            ON C.id_tm = T.id_tm
            WHERE T.periodo='invernale'
            AND T.frequenza in('festiva')
            AND NOT EXISTS(
            SELECT 1 FROM gbgar_serv_master M
            JOIN gbgar_serv_detail D ON M.id_master=D.id_master
            WHERE D.id_corsa=C.id_corsa
            AND M.data='$data_servizio');";
            $corse_da_svolgere = $Conn->query($query_corse_sql);        
    }//query relativo a periodo natalizio, giorno feriale
    if($orario_in_vigore==="natalizio" && $giorno_servizio==="feriale"){
            $query_corse_sql =
            "SELECT id_corsa,linea,gbgar_fermate.ubicazione as partenza,DATE_FORMAT(orario_corsa,'%H:%i') AS orario_corsa
            FROM gbgar_corse C
            JOIN gbgar_fermate
            ON C.partenza=gbgar_fermate.id_fermata
            JOIN gbgar_tab_marcia T
            ON C.id_tm = T.id_tm
            WHERE T.periodo='invernale'
            AND T.frequenza='feriale'
            AND NOT EXISTS(
            SELECT 1 FROM gbgar_serv_master M
            JOIN gbgar_serv_detail D ON M.id_master=D.id_master
            WHERE D.id_corsa=C.id_corsa
            AND M.data='$data_servizio');";
            $corse_da_svolgere = $Conn->query($query_corse_sql);
    }//query relativo a periodo natalizio, giorno festivo
    if($orario_in_vigore==="natalizio" && $giorno_servizio==="festivo"){
            $query_corse_sql =
            "SELECT id_corsa,linea,gbgar_fermate.ubicazione as partenza,DATE_FORMAT(orario_corsa,'%H:%i') AS orario_corsa
            FROM gbgar_corse C
            JOIN gbgar_fermate
            ON C.partenza=gbgar_fermate.id_fermata
            JOIN gbgar_tab_marcia T
            ON C.id_tm = T.id_tm
            WHERE T.periodo='invernale'
            AND T.frequenza='festiva'
            AND NOT EXISTS(
            SELECT 1 FROM gbgar_serv_master M
            JOIN gbgar_serv_detail D ON M.id_master=D.id_master
            WHERE D.id_corsa=C.id_corsa
            AND M.data='$data_servizio');";
            $corse_da_svolgere = $Conn->query($query_corse_sql);
    }//query relativo a periodo pasquale, giorno feriale
    if($orario_in_vigore==="pasquale" && $giorno_servizio==="feriale"){
            $query_corse_sql =
            "SELECT id_corsa,linea,gbgar_fermate.ubicazione as partenza,DATE_FORMAT(orario_corsa,'%H:%i') AS orario_corsa
            FROM gbgar_corse C
            JOIN gbgar_fermate
            ON C.partenza=gbgar_fermate.id_fermata
            JOIN gbgar_tab_marcia T
            ON C.id_tm = T.id_tm
            WHERE T.periodo='invernale'
            AND T.frequenza='feriale'
            AND NOT EXISTS(
            SELECT 1 FROM gbgar_serv_master M
            JOIN gbgar_serv_detail D ON M.id_master=D.id_master
            WHERE D.id_corsa=C.id_corsa
            AND M.data='$data_servizio');";
            $corse_da_svolgere = $Conn->query($query_corse_sql);
    }//query relativo a periodo estivo, feriale + sabato
    if($orario_in_vigore==="estivo" && $giorno_servizio==="feriale"|| $giorno_servizio==="sabato"){
            $query_corse_sql = 
            "SELECT id_corsa,linea,gbgar_fermate.ubicazione as partenza,DATE_FORMAT(orario_corsa,'%H:%i') AS orario_corsa 
            FROM gbgar_corse C
            JOIN gbgar_fermate
            ON C.partenza=gbgar_fermate.id_fermata
            JOIN gbgar_tab_marcia T
            ON C.id_tm = T.id_tm
            WHERE T.periodo='estivo'
            AND T.frequenza='feriale'
            AND NOT EXISTS(
            SELECT 1 FROM gbgar_serv_master M
            JOIN gbgar_serv_detail D ON M.id_master=D.id_master
            WHERE D.id_corsa = C.id_corsa
            AND M.data='$data_servizio');";
            $corse_da_svolgere = $Conn->query($query_corse_sql);
    }//query relativo a periodo estivo, giorno festivo
    if($orario_in_vigore==="estivo" && $giorno_servizio==="festivo"){
            $query_corse_sql = 
            "SELECT id_corsa,linea,gbgar_fermate.ubicazione as partenza,DATE_FORMAT(orario_corsa,'%H:%i') AS orario_corsa 
            FROM gbgar_corse C
            JOIN gbgar_fermate
            ON C.partenza=gbgar_fermate.id_fermata
            JOIN gbgar_tab_marcia T
            ON C.id_tm = T.id_tm
            WHERE T.periodo='estivo'
            AND T.frequenza='festiva'
            AND NOT EXISTS(
            SELECT 1 FROM gbgar_serv_master M
            JOIN gbgar_serv_detail D ON M.id_master=D.id_master
            WHERE D.id_corsa = C.id_corsa
            AND M.data='$data_servizio');";
            $corse_da_svolgere = $Conn->query($query_corse_sql);
    }elseif($corse_da_svolgere == FALSE){
            die("Errore nell'esecuzione della query:" . $query_linee_sql);
            }
    ?>
    
    </body>
    </html>
    

    Per avere in sostanza una sola query che con la data_servizio faccia lo stesso lavoro di selezione che fa questo script.

    Buona giornata.

    Filippo 

  • 25/08/2026 - pierpippo ha scritto:

    <!-- Questo script seleziona la corse che devono apparire nella select del form di gestione dei servizi -->

    25/08/2026 - pierpippo ha scritto:

    //DETERMINAZIONE DELLA DATA ORARIO/PERIODO IN VIGORE

    25/08/2026 - pierpippo ha scritto:

    //DETERMINAZIONE GIORNO FESTIVO

    ti servono questi dati, io estrapolo i dati inviando da php la richiesta al db, nell'esempio che segue ho filtrato gennaio

    WITH RECURSIVE calendario AS (
        SELECT DATE('2025-01-01') AS giorno  // DATA DI PARTENZA DELLA QUERY
        UNION ALL
    
        SELECT giorno + INTERVAL 1 DAY // MI SPOSTO LA DATA DI UN GIORNO PERCHè USO MINORE E MAGGIORE        
                                       //SENZA UGUALE
        FROM calendario
        WHERE giorno < '2025-01-31'   //DATA DI ARRIVO DELLA QUERY IN QUESTO CASO TUTTO GENNAIO
        ),
       
        // adesso trasformo la tabella festivita da verticale in orizzontale e la chiamo "periodi"
        // cioe' da id; descrizione; data; a id; descrizione; inizio; fine;
        // tu forse l'hai già in questo formato
        
        periodi AS (
        SELECT
            f1.nome,
            f1.data AS data_inizio,
            (
                SELECT MIN(f2.data)
                FROM festivita f2
                WHERE f2.nome = f1.nome
                  AND f2.tipo = 'fine'
                  AND f2.data > f1.data
            ) AS data_fine
        FROM festivita f1
        WHERE f1.tipo = 'inizio'
        )
    
    SELECT
        c.giorno,
    // qui controllo la data in quale caso ricade
        CASE
            // nella prima opzione, visto che nella tabella festivita non ci sono le domeniche controllo se la data è una domenica
            WHEN DAYOFWEEK(c.giorno) = 1  
                 OR EXISTS (    // controllo se domenica a meno che non sia una festa ricadente nella domenica
                    SELECT 1
                    FROM festivita f
                    WHERE f.data = c.giorno
                      AND f.tipo IN ('FISSO','VARIABILE')
                 )
            THEN 'FESTIVO'  // in entrambi i casi la metto come "festivo"
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'estivo'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 'ESTIVO'
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'scolastico'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 'SCOLASTICO'
    
            WHEN EXISTS (
              SELECT 1
              FROM periodi p
              WHERE p.nome = 'INVERNALE'
                AND c.giorno BETWEEN p.data_inizio AND p.data_fine
          )
          THEN 'INVERNALE'
    
          ELSE 'NESSUNO'
    
        END AS servizio,  // nome del secondo campo che puoi mettere a tuo piacimento
    
        CASE
            // come sopra ma stavolta inderisco il campo "numero_corse" ma tu puoi inserire il valore che vuoi
            WHEN DAYOFWEEK(c.giorno) = 1
                 OR EXISTS (
                    SELECT 1
                    FROM festivita f
                    WHERE f.data = c.giorno
                      AND f.tipo IN ('FISSO','VARIABILE')
                 )
            THEN 2
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'estivo'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 3
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'scolastico'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 5
    
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'INVERNALE'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 4
    
            ELSE 0
    
        END AS numero_corse  // qui puoi chiamare il campo come vuoi
    
    FROM calendario c
    ORDER BY c.giorno;
    
    // RISULTATO DAL 01/01/2025 AL 31/01/2025
    
    +------------+------------+--------------+
    | giorno     | servizio   | numero_corse |
    +------------+------------+--------------+
    | 2025-01-01 | FESTIVO    |            2 |
    | 2025-01-02 | INVERNALE  |            4 |
    | 2025-01-03 | INVERNALE  |            4 |
    | 2025-01-04 | INVERNALE  |            4 |
    | 2025-01-05 | FESTIVO    |            2 |
    | 2025-01-06 | FESTIVO    |            2 |
    | 2025-01-07 | SCOLASTICO |            5 |
    | 2025-01-08 | SCOLASTICO |            5 |
    | 2025-01-09 | SCOLASTICO |            5 |
    | 2025-01-10 | SCOLASTICO |            5 |
    | 2025-01-11 | SCOLASTICO |            5 |
    | 2025-01-12 | FESTIVO    |            2 |
    | 2025-01-13 | SCOLASTICO |            5 |
    | 2025-01-14 | SCOLASTICO |            5 |
    | 2025-01-15 | SCOLASTICO |            5 |
    | 2025-01-16 | SCOLASTICO |            5 |
    | 2025-01-17 | SCOLASTICO |            5 |
    | 2025-01-18 | SCOLASTICO |            5 |
    | 2025-01-19 | FESTIVO    |            2 |
    | 2025-01-20 | SCOLASTICO |            5 |
    | 2025-01-21 | SCOLASTICO |            5 |
    | 2025-01-22 | SCOLASTICO |            5 |
    | 2025-01-23 | SCOLASTICO |            5 |
    | 2025-01-24 | SCOLASTICO |            5 |
    | 2025-01-25 | SCOLASTICO |            5 |
    | 2025-01-26 | FESTIVO    |            2 |
    | 2025-01-27 | SCOLASTICO |            5 |
    | 2025-01-28 | SCOLASTICO |            5 |
    | 2025-01-29 | SCOLASTICO |            5 |
    | 2025-01-30 | SCOLASTICO |            5 |
    | 2025-01-31 | SCOLASTICO |            5 |
    +------------+------------+--------------+
    
    giorno lo passi tu, servizio è il risultato del primo CASE restituito in base alla data passata, numero_corse è il risultato del secondo CASE restituito in base alla data passata;

    hai il giorno passato a mysql e sai dalla colonna servizio (che puoi rinominare come vuoi) che tipo di giorno è.

    se selezionavo dal 26/01/25 al 26/01/25 ottenevo "festivo" e numero_corse = 2

    al posto di numero corse puoi mettere la frequenza in queste sezioni di query

    .....
    WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'scolastico'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 5 // al posto di 5 metti quello che vuoi...
    ...       

    25/08/2026 - pierpippo ha scritto:

    • innanzitutto valore "invernale" nel campo periodo  
    • e poi sia quelle che hanno valore "scolastico"  che quelle che hanno valore  "feriale" nel campo frequenza.

    fai le prove con il mio penultimo messaggio da console mysql e la sistemi al tuo bisogno.

    considera che le tabelle dati possono essere le tue, modificando i nomi tabelle di riferimento e relativi campi.

  • Ciao, ho fatto delle prove e mi pare che questa è la query che pare funzionare. 

    Quella che ho ricevuto il 24 agosto 14.18

    Ho corretto un paio di cose che ho evidenziato

    WITH periodo AS (
        SELECT
            descrizione_periodo,
    
            CASE descrizione_periodo
                WHEN 'periodo_pasquale'   THEN 'pasquale'
                WHEN 'periodo_natalizio'  THEN 'natalizio'
                WHEN 'periodo_estivo'     THEN 'estivo'
                WHEN 'periodo_invernale'  THEN 'invernale'
            END AS periodo
    
        FROM gbgar_periodi
    
        WHERE '2026-08-24' BETWEEN data_inizio AND data_fine
    
        ORDER BY
            CASE descrizione_periodo
                WHEN 'periodo_pasquale'   THEN 1
                WHEN 'periodo_natalizio'  THEN 2
                WHEN 'periodo_estivo'     THEN 3
                WHEN 'periodo_invernale'  THEN 4
                ELSE 99
            END
    
        LIMIT 1
    ),
    
    giorno AS (
        SELECT
            '2026-08-24' AS data_servizio,
    
            CASE
    
                WHEN DAYOFWEEK('2026-08-24') = 1
                  OR EXISTS (
                        SELECT 1
                        FROM gbgar_festivita f
                        WHERE f.GIORNO = '2026-08-24'
                    )
                THEN 'festiva'
    
                WHEN DAYOFWEEK('2026-08-24') > 1
    // cosi prendo tutti i giorni settimanali tranne la domenica ma non so se va in conflitto con il case precedente che controlla la domenica e le date festive fisse che facilmente sono anche infrasettimanali. 
                THEN 'feriale'
    
                ELSE 'scolastica'
    
            END AS frequenza
    )
    
    Non si puo mettere un case che mi definisca la frequenza feriale (THEN 'feriale') quando il periodo è estivo, natalizio e pasquale e la definisca invece scolastica (THEN 'scolastica') quando il periodo è invernale?
    
    SELECT
        c.ID_CORSA,
        c.ID_TM,
        c.LINEA,
        ic.UBICAZIONE AS PARTENZA,
        c.ORARIO_CORSA,
        fc.UBICAZIONE AS c.ARRIVO,
        c.FINE_CORSA,
        c.KM,
    
        p.periodo,
        g.frequenza
    
    FROM gbgar_corse c
    
    INNER JOIN gbgar_fermate ic
    ON c.PARTENZA = ic.ID_FERMATA
    INNER JOIN gbgar_fermate fc
    ON c.ARRIVO = fc.ID_FERMATA
    
    //cosi quando estraggo i valori per la mia tendina ho il nome della ferma di partenza corsa.
    
    INNER JOIN gbgar_tab_marcia tm
        ON tm.ID_TM = c.ID_TM
    
    CROSS JOIN periodo p
    CROSS JOIN giorno g
    
    WHERE
        tm.PERIODO = p.periodo
    
        AND (
            tm.FREQUENZA = g.frequenza
            OR tm.FREQUENZA = 'giornaliera'
        )
    
    ORDER BY
        c.ORARIO_CORSA;
    

    in rosa ho messo ciò che secondo me dovrebbe potersi aggiustare.

  • 26/08/2026 - pierpippo ha scritto:

    in rosa ho messo ciò che secondo me dovrebbe potersi aggiustare.

    non vedo nessun rosa...

    26/08/2026 - pierpippo ha scritto:

    WHEN DAYOFWEEK('2026-08-24') > 1 // cosi prendo tutti i giorni settimanali tranne la domenica ma non so se va in conflitto con il case precedente che controlla la domenica e le date festive fisse che facilmente sono anche infrasettimanali. THEN 'feriale'

    non essendo gemelli siamesi che condividono lo stesso cervello io l'ho interpretata così:

    giorno x è invernale, feriale e scolastico quindi tutti i mezzi fanno servizio

    giorno y è invernale, feriale ma le scuole sono chiuse (elezioni, allerta meteo ecc...) metti in settaggio che quel o quei giorni sono solo feriali e circolano i mezzi che non fanno servizio scuola (ammesso che sia così che lo hai previsto...

    quindi dopo then puoi mettere anche "tutti i mezzi" al posto di "invernale". io per invernale intendo quei giorni dove non c'è scuola (non tutti i mezzi operano), altrimenti, "scolastico" (tutti i mezzi sono operativi).

    nulla vieta di seguire la logica e mettere quello che vuoi. alla fine, se selezioni solo un giorno avrai come risultato:

    nel primo campo tabella risposta il giorno che hai passato tu da php

    nel secondo campo che nomini a piacimento con "AS campoestratto" trovi quello che hai passato con "then"

    nel terzo campo io ho messo un valore test con il numero di mezzi in servizio per quella data, ma tu puoi nominare il campo come ti viene più comodo e mettere il valore che ti serve per il programma.

    in sostanza, al posto di quegli if nidificati. passi la data, hai già i giorni caricati, i mezzi per tipo di giorno e passando la data ti restituisce un array (si, la query è sostanzialmente un array: è indicizzato e contiene valori, solo che si riempie da sola in base a cosa gli passi) ossia un record.

    se fai per intervallo di date ottieni una matrice di dati (record e campi).

    a mano dovresti aprire n query per estrapolare i dati da elaborare, calcolare che giorno è, sostituire i valori dell'array e utilizzare l'array...PECCHE'?

    lato mysql passi una data e buonanotte! hai tutto quello che ti serve.

    per autisti e mezzi la logica è la stessa, cambia che in base alla data ti viene fuori un elenco di mezzi e percorsi, lato automezzi, mentre lato autisti hai la lista x data degli autisti disponibili.

    Ti ho detto che ho fatto modifiche alla mia query che ha una logica un pò diversa, se riscontri errori la limiamo a dovere.

    buon lavoro.

  • 26/08/2026 - sihsandrea ha scritto:

    non vedo nessun rosa...

    Ops.. avevo evidenziato dei tratti di codice della query riportata sotto, per aiutarti a capire cosa intendevo ma a quanto pare le evidenziazioni non vengono trasmesse? boohhh 

    In ogni caso trovo una certa differenza tra questa query che sto provando in sql (sotto tuo invito nella tua risposta del 24/8), e anche comprendendo in parte, rispetto a quella che mi hai rimandato in seguito, della quale invece nn capisco assolutamente nulla.

    Ho provato a manipolare questa query cambiando la data servizio e "THEN 'feriale'" con 'scolastico' e con 'festivo' e mi pare che vada anche bene ma resta un solo problema secondo me. Cmq ho la sensazione che con questa query, di essere molto più vicino ad ottenere ciò che cerco.

    Anzi 2 problemi ma il secondo dovrebbe essere più facile.

    cmq ti dico cosa ho capito. Poi veniamo alla correzione della query, se possibile.

    problema 1: 

    questa query stabilisce dei "case" (sembra un po' lo swich di php) in base al periodo, prendendo data_inzio e data_fine di ogni periodo dalla tabella gbgar_periodi e verificando in quale di questi casi ricade la data_servizio che ovviamente, facendo dei test in console sql,  non è un parametro dinamico ma una stringa che vado a modificare a manina per vedere come reagisce la tabella risultante.

    Order by con limit 1 serve a far si che vengano ordinati i risultati e presi solo quelli del primo caso  in cui ci sono rispondenze. 

    Il secondo blocco poi va a confrontare la data per determinare se è feriale o festivo.

    io ho cambiato =7 con >1: perché sono andato a cercarmi la funzione DAYOFWEEK come funziona, penso che data_servizio deve essere non festivo se è vero che è maggiore di 1 (1=domenica).

    Quindi un valore minimo di 2 fino a quanto gli pare tanto al massimo avrà valore 7 se è sabato.

    Il problema sta quindi nel fatto che i giorni non festivi nel mio progetto, possono essere feriali o scolastici: quindi ho questa situazione:

    • periodo invernale: i feriali sono tutti scolastici 
      (tabelle di marcia (id_tm) valide, con frequenza feriale+scolastica+giornaliera)
    • periodo estivo/natalizio/pasquale: i feriali sono semplicemente feriali
      (tabelle valide con frequenza feriale+giornaliera) 

    Cmq ho visto che la query va a prendere, in ogni caso tutte le corse che sono in tabelle con frequenza 'giornaliera'.

    Questa query esamina però distintamente periodo e frequenza quindi per usare una unica query che prenderà data_servizio come parametro, devo chiedere a sql che mi definisca i giorni con valore >1 in due modi diversi a seconda del periodo. Ho capito bene? ...ed eventualmente è possibile?

    Oppure devo modificare le tabelle fisiche da cui questa query carica i dati?

    In questo caso penso che la tabella fisica da modificare sia gbgar_tab_marcia:

    tuttavia non saprei come modificarla esattamente.

    Problema 2 

    Il secondo problema invece sarebbe che il risultato della query dovrà cmq essere "epurato" delle corse che sono già presenti per la stessa data, in gbgar_serv_detail.

    quindi in questa query, penso in fondo dopo "order by c.ORARIO_CORSA;"  devo cmq inserire questo blocco di codice:

    AND NOT EXISTS(
            SELECT 1 FROM gbgar_serv_master m
            JOIN gbgar_serv_detail d ON m.id_master=d.id_master
            WHERE d.id_corsa=c.id_corsa
            AND m.data='$data_servizio');";

    Tuttavia è inutile per ora che risolvo il problema 2 finché non so se/come risolvere problema 1.

    WITH periodo AS (
       SELECT
           descrizione_periodo,
           CASE descrizione_periodo
               WHEN 'periodo_pasquale'   THEN 'pasquale'
               WHEN 'periodo_natalizio'  THEN 'natalizio'
               WHEN 'periodo_estivo'     THEN 'estivo'
               WHEN 'periodo_invernale'  THEN 'invernale'
           END AS periodo
       FROM gbgar_periodi
       WHERE '2026-08-27' BETWEEN data_inizio AND data_fine
       ORDER BY
           CASE descrizione_periodo
               WHEN 'periodo_pasquale'   THEN 1
               WHEN 'periodo_natalizio'  THEN 2
               WHEN 'periodo_estivo'     THEN 3
               WHEN 'periodo_invernale'  THEN 4
               ELSE 99
           END
       LIMIT 1
    ),
    giorno AS (
       SELECT
           '2026-08-27' AS data_servizio,
           CASE
               WHEN DAYOFWEEK('2026-08-27') = 1
                 OR EXISTS (
                       SELECT 1
                       FROM gbgar_festivita f
                       WHERE f.GIORNO = '2026-08-27'
                   )
               THEN 'festiva'
               WHEN DAYOFWEEK('2026-08-27') >1
               THEN 'feriale'
               ELSE 'nessuna'
           END AS frequenza
    )
    SELECT
       c.ID_CORSA,
       tm.TABELLA AS ID_TM,
       c.LINEA,
       ic.UBICAZIONE AS PARTENZA,
       c.ORARIO_CORSA,
       fc.UBICAZIONE AS ARRIVO,
       c.FINE_CORSA,
       c.KM,
       p.periodo,
       g.frequenza
    FROM gbgar_corse c
    INNER JOIN gbgar_fermate ic
    ON c.PARTENZA = ic.ID_FERMATA
    INNER JOIN gbgar_fermate fc
    ON c.ARRIVO = fc.ID_FERMATA
    INNER JOIN gbgar_tab_marcia tm
       ON tm.ID_TM = c.ID_TM    
    CROSS JOIN periodo p
    CROSS JOIN giorno g
    WHERE
       tm.PERIODO = p.periodo
       AND (
           tm.FREQUENZA = g.frequenza
           OR tm.FREQUENZA = 'giornaliera'
       )
    ORDER BY
       c.ORARIO_CORSA;

    Buona giornata.

Devi accedere o registrarti per scrivere nel forum
76 risposte