Determinazione data

di pierpippo il
76 risposte

76 Risposte - Pagina 5

  • 27/08/2026 - pierpippo ha scritto:

    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'.

    uhm.... non festivi possono essere feriali o scolastici? ti avevo detti che scolastico è un sottoinsieme di feriale.

    adesso mi salta all'occhio "giornaliera". che significa?

    a che serve questa tabella?

    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)

    la query ti restituisce

    // 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 |
    +------------+------------+--------------+

    dove il campo servizio lo puoi chiamare tranquillamente "periodo" come nella tua gbgar_tab_marcia

    frequenza che cosa indica? alla fermata dell'autobus indica ogni quanto tempo passa il mezzo (30 min... 45 min... ecc), qui cosa indica?

    il campo tabella cosa indica? hai valori ripetuti.

    nella query il campo numero_corse per me indica quanti mezzi sono coinvolti (il tuo 913 lun-sab).

    che collegamento hai con le frequenze della tabella marcia? e cosa è la tabella marcia?

    27/08/2026 - pierpippo ha scritto:

    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.

    la query ti risolve il problema data>>periodo

    epurato che significa?

    avrai una tabella di partenza filtrata in base a cosa ti restituisce la query (il tuo array di partenza).

    quindi:

    variabili: data (che già hai impostato e passato alla query), periodo che e query.servizio, query.numerocorse

    quindi lanci una vista tabellare con le condizioni di periodo e numero corse (una tua tabella di settaggio) con il modello "not in..." oppure "IS NULL".

    ti ho fatto un esempio in altro 3d.

    inserisci le corse

    update tabellax bla bla... prendendo i valori dalla tabella di partenza

    aggiorni la vista e aggiorni la tabella "diario".

    se togli dal diario (delete bla bla from diario...) aggiorni ancora la vista di partenza.

    ma questa è un'altra gestione.

    metti la tabella dei mezzi disponibili per periodo

    segue la tabella assegnata (diario)

    metti un pulsante aggiungi alla tabella di partenza e fai la insert

    un pulsante alla tabella diario per eliminare in record selezionato e renderlo disponibile nuovamente alla tabella di partenza.

  • Ho uno scampolo di tempo e cerco di chiarire alcune cose.

    27/08/2026 - sihsandrea ha scritto:

    adesso mi salta all'occhio "giornaliera". che significa?

    significa che una corsa, se è prevista (è elencata) sia nella tabella di marcia che ha frequenza festiva, e in quella che è invece feriale/scolastica, significa che è giornaliera perché va effettuata a prescindere nel periodo in cui è in vigore l'orario che la prevede (estivo/invernale)

    Le macchine in circolazione non centrano nulla in effetti. Non devo creare un elenco di macchine in circolazione ma solo un elenco di corse che vanno eseguite o meno.

    Il progetto deve solo selezionare un elenco di corse che vanno evase in un dato giorno (data_servizio).

    27/08/2026 - sihsandrea ha scritto:

    a che serve questa tabella?

    +-------+-------------+-----------+-------------+
    | 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)

    Serve a collegare le corse con le tabelle di marcia che le elencano:

    Il campo id_tm è la chiave esterna di collegamento tra gbgar_corse e gbgar_tab_marcia.
    i valori del campo TABELLA si ripetono perché per es:

    la corsa delle 18.30 della linea L. 151  tabella 811 

    compare in 3 versioni della stessa tabella (811): 

    • tabella 811 invernale scolastica 
    • tabella 811 invernale sabato
    • tabella 811 festiva.

    Quindi ho messo un valore "giornaliera" tra quelli accettati nel campo frequenza (enum) perché quando andrò a popolare la tabella gbgar_corse (ora ha solo dei record di test), devo collegare ogni corsa, non solo alla tabella giusta ma anche alla versione della stessa tabella.

    Quindi se "data_servizio" ricade in periodo invernale ed è un giorno scolastico (lun-sab) che non coincide con una data festiva fissa,  

    il risultato della mia select deve comprendere:

    tutte le corse (id_corsa) che sono elencate nelle tabelle di marcia che hanno:

    • periodo: invernale
    • frequenza: scolastica e giornaliera

    ...meno quelle già presenti in gbgar_serv_detail perchè se sono già assegnate per la stesa data_servizio ovviamente dal risultato della mia select non devono più apparire. (questo cmq penso di averlo gia risolto perchè me lo avevi già spiegato)

    27/08/2026 - sihsandrea ha scritto:

    frequenza che cosa indica? alla fermata dell'autobus indica ogni quanto tempo passa il mezzo (30 min... 45 min... ecc), qui cosa indica?

    Per frequenza non intendo la frequenza di passaggi bus ma la frequenza con cui si ripete una corsa nei giorni. 

    • frequenza='scolastica' significa che la tabella di marcia comprende corse  che vanno fatte nei giorni scolastici (che sono anche feriali).
    • frequenza='feriale'  tabella di marcia le cui corse sono svolte in giorni feriali in cui son chiuse le scuole, vale a dire in cui i giorni sono feriali ma ricadono nel periodo estivi o nel periodo natalizio o nel periodo pasquale.

    Durante il periodo invernale, tranne la parentesi natalizia e pasquale, le tabelle feriali sono quindi definite scolastiche, è solo quando le scuole sono chiuse che sono semplicemente feriali.

    Quindi per esempio, la stessa tabella (Tabella 919 invernale scol.) , valida per lunedì 21 dicembre ha la corsa L. 156  Ravenna - Forlì delle ore 6.30 (giorno scolastico), ma  per il 24 dicembre la stessa tabella non è valida, e nella tabella 919 invernale feriale, invece, la corsa citata non esiste perché il giovedì 24 dicembre è feriale a tutti gli effetti ma non scolastico.
    Oppure magari esiste ma non per le 6.30 ma per le 7.10, quindi avendo un orario diverso è un'altra corsa e avrà in id_corsa diverso in gbgar_corse e sarà collegata ad un id_tm diverso, anche se il record con quel id_tm in gbgar_tab_marcia, potrebbe avere lo stesso valore nel campo "tabella"(919) e nel campo periodo (invernale), ma nel campo "frequenza", avrà valore 'feriale' e non 'scolastico'.

    Ecco perché ho pensato mi servisse distinguere un giorno feriale da uno scolastico, ma la distinzione non è in base al giorno della settimana, ma in base al periodo. Quindi per fare un altro esempio un martedì è feriale se... per dire... è il martedì seguente la pasquetta (ultimo gg di chiusura scuole per le vacanze pasquali), ma il martedì  successivo è si feriale ma ai fini del progetto va definito scolastico.

    27/08/2026 - sihsandrea ha scritto:

    nella query il campo numero_corse per me indica quanti mezzi sono coinvolti (il tuo 913 lun-sab).

    che collegamento hai con le frequenze della tabella marcia? e cosa è la tabella marcia?

    Numero_corse a me nn serve a nulla. 
    tabella 913 lun-sab è la tabella nr. 913 valida nel periodo invernale giorni scolastici. Sti andicappati della Start Romagna hanno creato tabelle indentiche con le stesse corse, una la chiamano 913 scol. lun-ven e l'altra  913 scol. sabato :-| ma sono identiche, stesse corse stessi orari. !!!
    Ha senso ? per me no...  quindi la tab 913 lun-sab ovvia a questa cosa assurda, evita ben più numerosi valori ripetuti inutilmente.

    Pensa che la tabella invernale  919 esiste anche nella versione 919s che sta per sabato,
    ma in questo caso alcune corse non sono le stesse, (il sabato ci sono due corse in meno),

    Ecco ora che mi ci fai pensare mi tocca anche controllare in query che il giorno, oltre ad essere festivo e feriale, anche che  sia o meno un sabato.
    (me ne stavo dimenticando).

    Su cosa sia la tabella di marcia ora spero di avertelo chiarito.

    Lo scampolo di tempo è finito .

    Grazie e Buona serata. 

  • 27/08/2026 - pierpippo ha scritto:

    Serve a collegare le corse con le tabelle di marcia che le elencano:

    Ok, quindi la query invece di restituire

    +------------+------------+--------------+
    | 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 

    Deve restituire

    +------------+------------+--------------+
    | giorno     | servizio   | frequenza |
    +------------+------------+--------------+
    | 2025-01-01 | FESTIVO    | giornaliero  |
    | 2025-01-02 | INVERNALE  | scolastico   |
    | 2025-01-03 | INVERNALE  | feriale      |
    |Ecc...

    Considerando che giornaliero è sempre coinvolto lo estrapolerei a priori.

    I dati restituiti dalla query devono essere

    Data|servizio|frequenza

    Da qui prelevi i dati e li passi alla nuova query (tabella vista)

    Devo modificare la fonte della prima query in modo da avere la lista corretta delle frequenze.

    Sempre se ho capito bene...

  • OK HO RIVISTO E CORRETTO LA QUERY.

    INTANTO SOSTITUISCO LA MIA TABELLA CONFIGURAZIONE CORSE CON LA TUA gbgar_tab_marcia.

    WITH RECURSIVE calendario AS (
        SELECT CAST(@data_dal AS DATE) AS giorno
    
        UNION ALL
    
        SELECT giorno + INTERVAL 1 DAY
        FROM calendario
        WHERE giorno < CAST(@data_al AS DATE)
    ),
    
    periodi AS (
        SELECT
            LOWER(f1.nome) AS nome,
            f1.data AS data_inizio,
            (
                SELECT MIN(f2.data)
                FROM festivita f2
                WHERE LOWER(f2.nome) = LOWER(f1.nome)
                  AND f2.tipo = 'fine'
                  AND f2.data > f1.data
            ) AS data_fine
        FROM festivita f1
        WHERE f1.tipo = 'inizio'
    )
    
    SELECT
        c.giorno AS data,
    
        CASE
            /* DOMENICA O FESTIVITÀ */
            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'
    
            /* PERIODO ESTIVO */
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'estivo'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 'ESTIVO'
    
            /* TUTTO IL RESTO È INVERNALE */
            ELSE 'INVERNALE'
        END AS servizio,
    
        CASE
            /* DOMENICA O FESTIVITÀ */
            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'
    
            /* ESTIVO */
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'estivo'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 'feriale'
    
            /* INVERNALE SCOLASTICO */
            WHEN EXISTS (
                SELECT 1
                FROM periodi p
                WHERE p.nome = 'scolastico'
                  AND c.giorno BETWEEN p.data_inizio AND p.data_fine
            )
            THEN 'scolastica'
    
            /* INVERNALE NON SCOLASTICO */
            ELSE 'giornaliera'
        END AS frequenza
    
    FROM calendario c
    ORDER BY c.giorno;

    ED OTTENGO QUESTA (IO L'HO FATTA PER PERIODO DAL 01/01/25 AL 15/09/25)

    +------------+------------+------------+
    | data       | servizio   | frequenza  |
    +------------+------------+------------+
    | 2025-01-01 | FESTIVO    | festivo    |
    | 2025-01-02 | INVERNALE  | giornaliera|
    | 2025-01-03 | INVERNALE  | giornaliera|
    | 2025-01-04 | INVERNALE  | giornaliera|
    | 2025-01-05 | FESTIVO    | festivo    |
    | 2025-01-06 | FESTIVO    | festivo    |
    | 2025-01-07 | INVERNALE  | scolastica |
    | 2025-01-08 | INVERNALE  | scolastica |
    | ...        | ...        | ...        |
    | 2025-07-15 | INVERNALE  | scolastica |
    | 2025-07-16 | ESTIVO     | feriale    |
    | ...        | ...        | ...        |
    | 2025-09-14 | ESTIVO     | feriale    |
    | 2025-09-15 | INVERNALE  | scolastica |
    +------------+------------+------------+

    LA SECONDA QUERY PRENDE I VALORI IN BASE AL GIORNO E MOSTRA QUALI MARCE PRELEVARE DALLA TABELLA gbgar_tab_marcia.

    quindi PHP prende, ad esempio:

    2025-01-02 | INVERNALE | giornaliera

    e passa:

    @periodo   = 'invernale'
    @frequenza = 'giornaliera'

    La query sulle tabelle marcia deve essere:

    SELECT *
    FROM gbgar_tab_marcia
    WHERE LOWER(PERIODO) = LOWER(@periodo)
    AND (
           LOWER(FREQUENZA) IN ('giornaliera', 'feriale')
           OR LOWER(FREQUENZA) = LOWER(@frequenza)
    );

    quindi abbiamo che la prima query decide quale servizio/frequenza vale in quella data (il tuo array dinamico in sembianze sql); la seconda query usa quella decisione per individuare le TABELLA corrette in gbgar_tab_marcia; poi da questa fai le JOIN verso le tabelle delle corse e tutte quelle che ti servono(percorsi, fermate ecc...).

  • Ok ma vorrei capire perchè il 24 agosto mi hai mandato quanto ti cito sotto

    24/08/2026 - sihsandrea ha scritto:

    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;

    E me la sono studiata facendo varie prove ....

    A parte il fatto che data_servizio è inserita staticamente e non come parametro visto che siamo in console sql va bene ...
    questa mi sembrava la query più comprensibile rispetto quanto mi hai mandato dopo, ho creduto che avessi capito cosa volessi ottenere e che nn centravano le macchine utilizzate e quant'altro.

    Poi ricevendo risposte sempre dallo stesso Sihsandrea in merito ad alcune cose volevo correggere di questa query, ho avuto l'impressione insomma che rispondessero due persone diverse.... e ho smesso di capirci quanto stavo finalmente iniziando a comprendere.

    Cmq.

    Mi sono accorto di un problemino al quale nn avevo pensato che riguarda il sabato:

    Ho paura che non sia sufficiente controllare che data_servizio ricada in periodo invernale o estivo o natalizio o pasquale, e che sia festivo o feriale, ma anche che sia o meno un sabato perché purtroppo mi sono accorto che alcune tabelle denominate col consueto numero seguito da s tipo ad es 919s differiscono dalla tabella denominata con lo stesso numero: 919 (senza s) solo per il fatto che presentano le stesse corse meno alcune.

    Quindi credo che nella tabella gbgar_tab_marcia, di dover aggiungere un valore ammesso dal campo frequenza aggiungendo il valore 'sabato'.

    Database changed
    MariaDB [gbgarage_test]> DESCRIBE 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','sabato','scolastica','festiva','giornaliera') | NO   |     | NULL    |                |
    +-----------+------------------------------------------------------+------+-----+---------+----------------+
    

     Di conseguenza, nella tabella gbgar_corse, i record delle corse (id_corsa) che andrebbero collegate ad entrambi gli id_tm (quello relativo alla tabella 919 e quello relativo alla tabella 919s), mi tocca ripeterli ?

    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  |
    |     6 | 919 lun-ven | invernale | scolastica  |
    |     7 | 919s        | invernale | sabato      |
    +-------+-------------+-----------+-------------+
    7 rows in set (0,001 sec)
    

    Non so esattamente come trattare questo problemino.

    O posso collegare un id_corsa a due id_tm? boohhh

    Cioè a me serve quindi che se data_servizio è sabato venga presa in considerazione l'id_tm relativo alla tabella di marcia 919s che esclude due corse lasciando invariate le altre.

    Credo di dover sciogliere questo nodo prima di proseguire. 

    Buona serata.

  • 28/08/2026 - pierpippo ha scritto:

    Di conseguenza, nella tabella gbgar_corse, i record delle corse (id_corsa) che andrebbero collegate ad entrambi gli id_tm (quello relativo alla tabella 919 e quello relativo alla tabella 919s), mi tocca ripeterli ?

    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  |
    |     6 | 919 lun-ven | invernale | scolastica  |
    |     7 | 919s        | invernale | sabato      |
    +-------+-------------+-----------+-------------+
    7 rows in set (0,001 sec)
    

    Non so esattamente come trattare questo problemino.

    sono sempre io a rispondere, ti ho scritto come parametrizzare la query e come passare i parametri da php, le prove le faccio direttamente in consolle mysql per velocizzare il tutto ma, anche nel rispetto delle regole, non posso darti la pappa pronta, tuttavia, se rileggi tutte le risposte hai tutti gli elementi per parametrizzarla.

    ti ho scritto che in base alla tabella marce avrei modificato la query affinchè diventasse simile alla tabella marce con in più la data.

    per il sabato, basta che aggiungi la ricerca del sabato (dayofweek) nel calendario, come fai per la domenica ma passi il valore "sabato".

    l'ultima query, quella dopo aver stabilito che tipo di giorno è serve per filtrare i dati della tabella marce.

    mi hai dato dei paletti:

    - giornaliero sempre

    - invernale sempre

    - scolastico solo se giorno scolastico

    - festivo solo i festivi.

    prendendo i dati dalla tabella marce per il giorno invernale scolastico deve estrarre:

    
    +-------+-------------+-----------+-------------+
    | ID_TM | TABELLA     | PERIODO   | FREQUENZA   |
    +-------+-------------+-----------+-------------+
    |     1 | 913 lun-sab | invernale | scolastica  |
    |     2 | 912 lun-sab | invernale | scolastica  |
    |     4 | 811         | invernale | giornaliera |
    |     5 | 811         | invernale | scolastica  |
    |     6 | 919 lun-ven | invernale | scolastica  |
    +-------+-------------+-----------+-------------+

    che mi sembra siano raggruppamenti di corse(?).

    se il giorno x è invernale sabato estrae

    
    +-------+-------------+-----------+-------------+
    | ID_TM | TABELLA     | PERIODO   | FREQUENZA   |
    +-------+-------------+-----------+-------------+
    |     4 | 811         | invernale | giornaliera |
    |     7 | 919s        | invernale | sabato      |
    +-------+-------------+-----------+-------------+

    almeno così ho capito...

    se è estivo

    
    +-------+-------------+-----------+-------------+
    | ID_TM | TABELLA     | PERIODO   | FREQUENZA   |
    +-------+-------------+-----------+-------------+
    |     3 | 919 lun-sab | estivo    | feriale     |
    +-------+-------------+-----------+-------------+

    correggimi se sbaglio...

    p.s. ovviamente la query primaria ti riporta il periodo e la frequenza variabili (anche aggiungendo come frequenza "sabato").

    a queste devi estrarre quelle fisse in base al periodo, ma essendo fisse, se non ti piace la query che ho messo, puoi fare più union

    // - giornaliero sempre
    select * from tuatabella where periodo=[parametroperiodo] and frequenza="giornaliera"
    union
    
    // - invernale sempre
    select * from tuatabella where periodo=[parametroperiodo] and frequenza="invernale" (o forse la chiami feriale)
    union
    
    // - scolastico solo se giorno scolastico
    select * from tuatabella where periodo=[parametroperiodo] 
         and (frequenza=[parametrofrequenza] and [parametrofrequenza]<>'') 
    // in questo caso se non esiste la frequenza non estrae nulla
    union
       
    // - festivo solo i festivi.
    select * from tuatabella where periodo=[parametroperiodo] and frequenza="festivo" 

    28/08/2026 - pierpippo ha scritto:

    Ho paura che non sia sufficiente controllare che data_servizio ricada in periodo invernale o estivo o natalizio o pasquale, e che sia festivo o feriale, ma anche che sia o meno un sabato perché purtroppo mi sono accorto che alcune tabelle denominate col consueto numero seguito da s tipo ad es 919s differiscono dalla tabella denominata con lo stesso numero: 919 (senza s) solo per il fatto che presentano le stesse corse meno alcune.

    ogni volta che dai un dato in più la query va istruita.

    quando scrivo periodo=[parametroperiodo] è una convenzione generica, su mysql diventa periodo=@periodo (o come chiami il parametro) da php invece lo passi per come abbiamo visto in precedenza.

  • 29/08/2026 - sihsandrea ha scritto:

    anche nel rispetto delle regole, non posso darti la pappa pronta

    Mi rendo conto di questo.

    Tuttavia, francamente mi pare di fare mezzo passo avanti e tre indietro.

    Non credo che mi serva fare delle union. 

    Vorrei capire perché mi hai suggerito questa:

    che poi in seguito sembra esser stata ignorata.

    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-09-19' 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-09-19' AS data_servizio,
    
            CASE
    
                WHEN DAYOFWEEK('2026-09-19') = 1
                  OR EXISTS (
                        SELECT 1
                        FROM gbgar_festivita f
                        WHERE f.GIORNO = '2026-09-19'
                    )
                THEN 'festiva'
                
                WHEN DAYOFWEEK('2026-09-19') > 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;

    A me mi era parsa subito più inerente al mio scopo:

    non ha union ma le cross join.

    d’altronde devo collegare ogni id_tm  di gbgar_tab_marcia a vari id_corsa di gbgar_corse.

    Ora partendo da questa:

    Rispetto al tuo suggerimento ho solo aggiunto una self join sulla tabella gbgar_fermate per avere il nome delle fermate e non solo l'anonimo id_fermata.

    E giocato con varie date per vedere le risposte.

    Mi son reso conto che però funziona cambiando a mano THEN 'feriale' con THEN 'scolatica' in base alla data.

    Quindi io ho pensato di procedere cosi:

    innanzi tutto devo correggere le tabelle sorgenti implicate:

    gbgar_tab_marcia:
     aggiungendo al campo FREQUENZA il valore enum(...'sabato'), a quelli già esistenti (giornaliera, festiva, feriale, scolastica); 
    e
    gbgar_corse: aggiungendogli una colonna, sempre collegata a gbgar_tab_marcia.id_tm,
    per risolvere il fatto di avere tabelle_di_marcia che differiscono il sabato rispetto agli altri giorni scolastici/feriali, tipo 919 (lun-ven) e 919s (sabato).

    poi aggiungo questo:

    WHEN DAYOFWEEK('2026-09-19') = 7
                THEN 'sabato'

     Per definire se la data è un sabato.

    Se è giusto mi resterebbe a sto punto solo una questione:

    analogamente a questo:

    WHERE '2026-09-19' BETWEEN data_inizio AND data_fine

    che pone la condizione secondo la quale si verifica uno degli:

    			WHEN 'periodo_pasquale'   THEN 'pasquale'
                WHEN 'periodo_natalizio'  THEN 'natalizio'
                WHEN 'periodo_estivo'     THEN 'estivo'
                WHEN 'periodo_invernale'  THEN 'invernale'
            END AS periodo
    

     Si possa fare all'interno della query la cosa analoga in 

    giorno AS (
        SELECT.....

    affinché si possa distinguere  tra 'feriale' e 'scolastico' in base a then 'periodo'.

    Dopo di che la select finale mi tira fuori una tabella con le corse che vanno evase nella data (qui inserita a mano ma che sarà in php rappresentata dalla variabile $data_servizio).

     alla quale devo aggiungere, penso in fondo dopo order by c.ORARIO_CORSA:

    ...
    ORDER BY
        c.ORARIO_CORSA
    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');

    Per togliere (epurare non ti piace), dalla lista gli id_corsa che appaiono per  la stessa data nelle tabella gbgar_serv_detail.

    Buona serata

    Filippo

  • 29/08/2026 - pierpippo ha scritto:

    Tuttavia, francamente mi pare di fare mezzo passo avanti e tre indietro.

    ho rivisto le prime risposte, io ti dicevo di crearti il calendario da un form a parte annuale o anche da data a data (dietro tua richiesta) e di salvarlo.

    al momento di inserire le corse, o quello che devi inserire, basta fare una join del calendario dal al che hai il tipo di giornata e periodo.

    nel frattempo si sono aggiunte altre informazioni. non conoscendo ne il tipo di lavoro che devi svolgere, ne le tabelle coinvolte, con l'ultima ho messo nel calendario (quello che ti restituisce data, periodo e frequenza) il periodo e la frequenza in modo da rispecchiare la tua tabella gbgar_tab_marcia.

    quindi da php passi la data, la query su calendario ti dice che tipo di giorno è quella data e da li puoi anche faree la join alla tabella gbgar_tab_marcia.

    29/08/2026 - pierpippo ha scritto:

    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' )

    nell'ultima ho anche legato la tabella gbgar_fermate citata sopra, ma puoi fermarti alla precedente.

    rinnovo il consiglio di gestire a parte il calendario. Visto che vuoi gestirlo a pezzetti, se calendario per una data no da record, allora mandi un messaggino di inserire il calendario e rilanci dal form di settaggio le date dal al mancanti. poi riprendi normalmente.

    mi hai detto che ci sono corse giornaliere, corse scolastiche ecc... quindi la tabella calendario ti da quelle che hanno una frequenza specifica, le altre le estrapoli passando gli altri parametri facendo la union.

    il calendario genera 365/366 record, nulla di pesante ma ti permette di gestire la data evitando di ripetere ogni volta la query.

    spero di essere stato più chiaro.

  • 29/08/2026 - pierpippo ha scritto:

    Si possa fare all'interno della query la cosa analoga in 

    giorno AS (
        SELECT.....

    affinché si possa distinguere  tra 'feriale' e 'scolastico' in base a then 'periodo'.

    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  |
    |     6 | 919 lun-ven | invernale | scolastica  |
    |     7 | 919s        | invernale | sabato      |
    +-------+-------------+-----------+-------------+
    7 rows in set (0,001 sec)

    hai detto che invernale hai 

    - sempre giornaliera

    - sempre feriale

    - potrebbe essere scolastica

    in base alla data passata restituisce

    data | periodo | frequenza |

    in base a quello che hai detto l'unica incognita è se è scolastica perchè è sempre feriale (altrimenti ti porta festivo o sabato) ed è sempre e comunque giornaliera.

    quindi 

    select ... where invernale and giornaliera

    union

    select .... where invernale and (feriale and frequenza <>sabato or festivo)

    union

    select .... where invernale and (frequenza =scolastica)

    per mostrare

    
    +-------+-------------+-----------+-------------+
    | ID_TM | TABELLA     | PERIODO   | FREQUENZA   |
    +-------+-------------+-----------+-------------+
    |     1 | 913 lun-sab | invernale | scolastica  |
    |     2 | 912 lun-sab | invernale | scolastica  |
    
    |     4 | 811         | invernale | giornaliera |
    |     5 | 811         | invernale | scolastica  |
    |     6 | 919 lun-ven | invernale | scolastica  |
        |
    +-------+-------------+-----------+-------------+
     se invernale da lun a ven scolastico
     
    
    +-------+-------------+-----------+-------------+
    | ID_TM | TABELLA     | PERIODO   | FREQUENZA   |
    +-------+-------------+-----------+-------------+
    |     4 | 811         | invernale | giornaliera |
    |     7 | 919s        | invernale | sabato      |
    +-------+-------------+-----------+-------------+
    
    se invernale di sabato

    o mi sono perso qualcosa?

  • 31/08/2026 - sihsandrea ha scritto:

    hai detto che invernale hai 

    - sempre giornaliera

    - sempre feriale

    - potrebbe essere scolastica

    in base alla data passata restituisce

    Più esattamente ho:

    • corse legate a id_tm con frequenza='giornaliera'  --> 
      corse che vengono effettuate tutti i giorni indistintamente cioé da lun da dom festivi fissi compresi.
      (pochissimi casi ma vanno cmq considerati);
    • corse legate a id_tm con frequenza='feriale'-->
      corse che vanno effettuate nei giorni feriali. 
      I giorni feriali esistono nel periodo estivo, natalizio e pasquale.(scuole chiuse).
    • Durante il periodo invernale i giorni feriali sono definiti scolastici.

    Allo stato attuale in cui non ho ancora inquadrato la query corretta per gestire il tutto solo con sql, ho una sorta di script ibrido dove uso php per :

    definire il periodo
    definire il giorno

    e poi imposto tutta una serie di condizioni ad incrociare le casistiche necessarie per periodi e giorni.

    Per ogni condizione: if($orario_in_vigore='invernale' && .....) {sql="select ...."}

    imposto una query dove sostanzialmente cambia solo ciò che metto in WHERE.....

    un esempio è il seguente:

    //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;
    }
    
    //gli eco li usavo per controllare se tutto funzinasse. poi non li ho cancellati ma solo commentati.
    
    //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')<6){
            $giorno_servizio="feriale";
            echo "<br>". $giorno_servizio;        
    }elseif($dayweek->format('w')==6){
            $giorno_servizio="sabato";
            echo"<br>". $giorno_servizio;
    }
    
    
    //query relativo a periodo invernale, giorno scolastico lun-sab
    if($orario_in_vigore==="invernale" && $giorno_servizio==='feriale'){
            $query_corse_sql =
            "SELECT id_corsa,linea,f.ubicazione as partenza,DATE_FORMAT(orario_corsa,'%H:%i') AS orario_corsa
            FROM gbgar_corse C
            JOIN gbgar_fermate f
            ON C.partenza=f.id_fermata
            JOIN gbgar_tab_marcia T
            ON C.id_tm = T.id_tm
            WHERE T.periodo='invernale'
            AND T.frequenza IN('lun-ven-scol','sab-scol','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')
            ORDER BY orario_corsa;";
            $corse_da_svolgere = $Conn->query($query_corse_sql);
            ....

    Come vedi per definire il periodo ho dovuto fare diverse condizioni perché il periodo invernale è interrotto da quello natalizio e pasquale durante e i quali i gg scolastici non ci sono appunto ma ci son al loro posto  quelli feriali.

    Ovviamente va da se che una corsa se è scolastica non appare in una tabella di marcia feriale.
    Una corsa feriale invece può apparire sia in una tabella scolastica (orario pomeridiano), sia nella tabella di marcia che ha lo stesso numero di tabella di marcia ma vale nei feriali (non scolastici) quindi entra in vigore nel periodo natalizio e pasquale. 

    Se il periodo è estivo ovviamente i feriali non sono mai scolastici. 

    Purtroppo una certa ridondanza è inevitabile perché potrò avere in gbgar_tab_marcia, sia una tabella di marcia es. 919 invernale scolastica e una 919 invernale feriale (non scolastica).

    Anche la tabella gbgar_corse avrà certi valori inevitabilmente ripetuti perché la stessa corsa magari differisce perché se scolastica si allunga nel percorso a raggiungere un plesso scolastico limitrofo mentre se è feriale la stessa corsa è limitata ad un capolinea diverso, quindi mi tocca avere due record diversi se voglio distinguere la corsa che deve essere collegata ad una o ad un altra tabella di marcia.

    Ho dovuto definire anche il sabato oltre a festivo e feriale.
    Per ovviare al problema delle corse che nello stesso periodo variano anche tra i giorni scolastici tipo appunto il sabato. (anche qua pochi casi cioè poche corse ma purtroppo vanno considerate.)

    Anche la tabella gbgar_tab_marcia è cambiata:

    MariaDB [gbgarage_test]> DESCRIBE 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','sab-fer','scolastica','lun-ven-scol','sab-scol','festiva','giornaliera') | YES  |     | NULL    |                |
    +-----------+------------------------------------------------------------------------------------------+------+-----+---------+----------------+
    4 rows in set (0,001 sec)
     

    Ho dovuto inserire in FREQUENZA nuovi valori:
     consultando le tabelle di marcia cartacee del periodo invernale 25/26 che dovrebbero essere quasi sicuramente le stesse che avremo per il prossimo invernale 26/27, emerge che la diversificazione necessaria è più articolata di quanto preventivato:

    il campo è di tipo enum(....) 

    • feriale: serve per  tabelle di marcia dei gg. feriali (non scolastici);
    • sab-fer: l'ho aggiunto per sicurezza, potrebbe saltar fuori infatti che serve differenziare il sabato anche nei gg. feriali non solo nei giorni scolastici.
    • scolastica: giorni scolastici da lunedì a sabato. Tabelle di marcia scolastiche che restano uguali tutti i gg della settimana
    • lun-ven-scol: T.d.M. scolastiche che cambiano il sabato.
    • sab-scol:  T.d.M. scolastiche per il sabato .
    • festiva: T.d.M. festive
    • giornaliera: T.d.M.  che in realtà non esiste nelle T.d.M. cartacee, tuttavia esistono corse che nel cartaceo sono ridondate identiche in quattro T.d.M. (es 811 lun-ven-scol,  811 sab-scol, 811 feriale, e 811 festivo) Quindi nell'ambito dell'intero periodo invernale esistono sempre per cui ho pensato di inserire anche il valore giornaliera tra le frequenze disponibili per non dover aver 4 colonne in gbgar_corse per collegare  queste corse a 4 diversi id_tm. In questa maniera il collegamento tra gbgar_corse e gbgar_tab_marcia resta solo la colonna id_tm.

    Alla fine sottraggo gli id_corsa che sono già presenti con la stessa $data_servizio in gbgar_serv_detail. 

    Per ottenere una variabile  $corse_da_svolgere che contiene una lista di record differente in base al giorno di riferimento che è sempre $data_servizio.

    IL  tutto tu lo avresti fatto tutto da sql. 

    E qua viene il bello.

    Fare a meno di tutto il codice PHP usato per definire periodo e giorno e soprattutto per non avere tutta la serie di select sql ma una sola che fa tutto.

    Bene.... 

    mo ci provo. In linea di massima penso di aver capito ma non lo so. 

    Buona giornata.

    Filippo P

  • 01/09/2026 - pierpippo ha scritto:

    Allo stato attuale in cui non ho ancora inquadrato la query corretta per gestire il tutto solo con sql, ho una sorta di script ibrido dove uso php per :

    definire il periodo
    definire il giorno

    secondo me stai facendo confusione.

    da un modulo di settaggio, che sia il primo dell'anno o durante l'anno, devi aggiornare la tabella delle festività e successivamente creare o aggiornare il calendario. il calendario lo puoi gestire a rate: alla data x dell'anno n-1 lanci la query che genera il calendario per l'anno n.

    puoi fare per mese, trimestre, semestre o come più preferisci.

    e ti ritrovi due tabelle:

    +----+------------------+------------+-----------+
    | 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      |
    +----+------------------+------------+-----------+
    
    e il calendario
    +------------+------------+------------+
    | data       | servizio   | frequenza  |
    +------------+------------+------------+
    | 2025-01-01 | FESTIVO    | festivo    |
    | 2025-01-02 | INVERNALE  | giornaliera|
    | 2025-01-03 | INVERNALE  | giornaliera|
    | 2025-01-04 | INVERNALE  | giornaliera|
    | 2025-01-05 | FESTIVO    | festivo    |
    | 2025-01-06 | FESTIVO    | festivo    |
    | 2025-01-07 | INVERNALE  | scolastica |
    | 2025-01-08 | INVERNALE  | scolastica |
    | ...        | ...        | ...        |
    | 2025-07-15 | INVERNALE  | scolastica |
    | 2025-07-16 | ESTIVO     | feriale    |
    | ...        | ...        | ...        |
    | 2025-09-14 | ESTIVO     | feriale    |
    | 2025-09-15 | INVERNALE  | scolastica |
    +------------+------------+------------+

    queste operazioni le fai prima di accedere al modulo php che hai mostrato.

    ora, quello che stai facendo è selezionare una data per capire il periodo di riferimento...

    se la data è 15/07/2025

    select * from calendario where data='2025-07-15'
    
    ti restituisce
    +------------+------------+------------+
    | data       | servizio   | frequenza  |
    +------------+------------+------------+
    | 2025-07-15 | INVERNALE  | scolastica |
    +------------+------------+------------+

    sai che la data ha periodo invernale e frequenza scolastica (c'e' scuola).

    01/09/2026 - pierpippo ha scritto:

    il campo e enum(....) 

    • feriale: serve per  tabelle di marcia dei gg. feriali (non scolastici);

      in questo caso è scolastico

    • sab-fer: l'ho aggiunto per sicurezza, potrebbe saltar fuori che serve differenziare il sabato anche nei gg. feriali non scolastici.

      non è sabato

    • scolastica: giorni scolastici da lunedì a sabato. Tabelle di marcia scolastiche che restano uguali tutti i gg della settimana

      è scolastico quindi prendi quello che serve

    • lun-ven-scol: T.d.M. scolastiche che cambiano il sabato.

      compro una vocale....

    • sab-scol:  T.d.M. scolastiche per il sabato .

      idem compro una vocale...

    • festiva: T.d.M. festive

      sai che non è festivo

    • giornaliera: T.d.M.  che in realtà non esiste nelle T.d.M. cartacee, tuttavia esistono corse che nel cartaceo sono ridondate identiche in quattro T.d.M. (es 811 lun-ven-scol,  811 sab-scol, 811 feriale, e 811 festivo) Quindi nell'ambito dell'intero periodo invernale esistono sempre per cui ho pensato di inserire anche il valore giornaliera tra le frequenze disponibili per non dover aver 4 colonne in gbgar_corse per collegare  queste corse a 4 diversi id_tm quando ne posso avere uno che li comprende tutti e 4.

      questa a livello di programmazione non va bene...

      se sono sempre presenti le carichi e basta, non serve sapere che giorno è

    quindi invece di quelle if fai la select al calendario per sapere cosa ti serve.

    il calendario puoi estenderlo di campi se serve anche se non ne capisco la logica che stai usando, in questo modo.

    +------------+------------+------------+------------+------------+
    | data       | servizio   | frequenza  | sab-scol   |sab-fer
    +------------+------------+------------+------------+
    | 2025-01-01 | FESTIVO    | festivo    | no         | no
    | 2025-01-02 | INVERNALE  | giornaliera|
    | 2025-01-03 | INVERNALE  | giornaliera|
    | 2025-01-04 | INVERNALE  | giornaliera| no         | si
    | 2025-01-05 | FESTIVO    | festivo    |
    | 2025-01-06 | FESTIVO    | festivo    |
    | 2025-01-07 | INVERNALE  | scolastica |
    | 2025-01-08 | INVERNALE  | scolastica |
    | ...        | ...        | ...        |
    | 2025-07-15 | INVERNALE  | scolastica |
    | 2025-07-16 | ESTIVO     | feriale    |
    | ...        | ...        | ...        |
    | 2025-09-14 | ESTIVO     | feriale    |
    | 2025-09-15 | INVERNALE  | scolastica |
    +------------+------------+------------+------------+------------+

    così in base alla data che passi sai frequenza, periodo (servizio in origine), sabato scolastico, sabato feriale ecc...

  • Non ti seguo.

    Ripartiamo da questa query senza union senza calendario:

    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-09-19' 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-09-19' AS data_servizio,
    
            CASE
    
                WHEN DAYOFWEEK('2026-09-19') = 1
                  OR EXISTS (
                        SELECT 1
                        FROM gbgar_festivita f
                        WHERE f.GIORNO = '2026-09-19'
                    )
                THEN 'festiva'
    
                WHEN DAYOFWEEK('2026-09-19') > 1
                THEN 'scolastica'
                WHEN DAYOFWEEK('2026-09-19') = 7 
                THEN 'sab-scol'
    
                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;

    devo solo affinare per istruirla con tutti i valori incrociati per periodi e giorno.

    01/09/2026 - sihsandrea ha scritto:

    • lun-ven-scol: T.d.M. scolastiche che cambiano il sabato.

      compro una vocale....

    • sab-scol:  T.d.M. scolastiche per il sabato .

      idem compro una vocale...

    Ti do le vocali.

    avendo un un insieme di corse che si chiama tabella di marcia "919" (abbrev. TdM) contenente le corse A,B,C,D,E,F. 
    e un altro insieme di corse che si chiama TdM "919s" con dentro le corse ABDF (tutte meno C ed E).

    Le corse sono in gbgar_corse e gli insiemi (TdM) sono in gbgar_tab_marcia.

    Un estratto della tabella gbgar_corse ... gli altri campi ora nn ci interessano.

    +----------+-------+-------+
    | id_corsa | id_tm | linea |
    +----------+-------+-------+
    |        1 |     1 | L.157 |
    |        2 |     2 | L.157 |
    |        3 |     2 | L.157 |
    |        4 |     2 | L.159 |
    |        5 |     3 | L.141 |
    |        6 |     4 | L.151 |
    |        7 |     3 | L.140 |
    |        8 |     3 | L.140 |
    |        9 |     5 | L.151 |
    |       10 |     7 | L.145 |
    |       11 |     6 | L.145 |
    +----------+-------+-------+
    11 rows in set (0,001 sec)
    
    

    e la tabella gbgar_tab_marcia

    MariaDB [gbgarage_test]> SELECT * from gbgar_tab_marcia;
    +-------+---------------+-----------+--------------+
    | ID_TM | TABELLA       | PERIODO   | FREQUENZA    |
    +-------+---------------+-----------+--------------+
    |     1 | 913           | invernale | scolastica   |
    |     2 | 912           | invernale | scolastica   |
    |     3 | 919           | estivo    | feriale      |
    |     4 | 811           | invernale | giornaliera  |
    |     5 | 811           | invernale | scolastica   |
    |     6 | 919(lun-ven)  | invernale | lun-ven-scol |
    |     7 | 919s(lun-sab) | invernale | sab-scol     |
    +-------+---------------+-----------+--------------+
    7 rows in set (0,000 sec)
    

    ho dovuto aggiungere quei valori in frequenza e di cui hai "chiesto una vocale", per poter collegare le corse A,B,D,F alla tabella 919s, e le corse C ed E alla tabella 919.

    Attribuisco valore PERIODO='invernale' ad entrambe le TdM. e
    alla TdM 919 valore FREQUENZA='lun-ven-scol' (trad. scolastico da lunedì a venerdì), mentre
    alla TdM 919s valore FREQUENZA='sab-scol' (trad. sabato scolastico).

    Altrimenti come rappresento nelle tabella questa situazione?

    quindi nelle mie query select, differenziate ed ognuna inserita nel suo blocco if (php)  relativo,

    quando inserisco la clausola WHERE ...... poi arrivo ad un punto in cui ho:

    if($orario_in_vigore==="invernale" && $giorno_servizio==='feriale'){
    $query_corse_sql =
    ...
    WHERE T.periodo='invernale'  
    AND T.frequenza IN('lun-ven-scol','sab-scol','scolastica','giornaliera')
    ....
    ;}

    quindi in questa query che prende in considerazione un giorno invernale feriale (quindi scolastico), prendo le corse comprese nelle Tdm che hanno frequenza:

    • lun-ven-scol : le Tdm come la 919 che vale da lun a ven  per prendere anche le corse escluse dalla 919s
    • sab-scol : le altre corse della tabella 919s che valgono tutta la settimana
    • scolastica: le corse delle TdM che sono sempre quelle da lun a sabato
    • giornaliera: le corse che si eseguono sempre nell'ambito del periodo in vigore.

    oppure

    elseif($orario_in_vigore==="invernale" && $giorno_servizio==="sabato"){
    $query_corse_sql =
     .....
    WHERE T.periodo='invernale'
    AND T.frequenza IN('sab-scol','scolastica','giornaliera')
     .....
     ;}

    Qui analogamente, essendo considerato un sabato invernale quindi scolastico,
    analogamente prendo i valori della colonna  frequenza:

    • sab-scol : le corse delle TdM 919s che di sabato vanno effettuate,
    • scolastica: quelle che sono scolastiche e restano identiche da lun a sab.
    • giornaliera: quelle che vanno fatte sempre a prescindere.

    questa sarebbe la logica.

    La domanda è, rifacendomi alla query riportata inizialmente,

    Posso istruire la query di cui sopra affinché:

    nei giorni feriali del periodo invernale la frequenza è scolastica 
    i giorni feriali del periodo natalizio e pasquale la frequenza è feriale,

    ad es, chiedo:

    non si può, in linguaggio sql, avere una condizione tipo se periodo è invernale....

     WHEN DAYOFWEEK('2026-09-19') > 1
                THEN 'scolastica'

    altrimenti se periodo è natalizio o pasquale......

     WHEN DAYOFWEEK('2026-09-19') > 1
                THEN 'feriale'

    e via dicendo?

    Buona giornata.

  • 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-09-19' 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-09-19' AS data_servizio,
    
    --------------------------------------errore logico-------------------------------------------------
            CASE
    
                WHEN DAYOFWEEK('2026-09-19') = 1    //// solo domenica
                  OR EXISTS (
                        SELECT 1
                        FROM gbgar_festivita f
                        WHERE f.GIORNO = '2026-09-19'
                    )
                THEN 'festiva'
    
                WHEN DAYOFWEEK('2026-09-19') > 1   ///// da lun a sab
                THEN 'scolastica'
                WHEN DAYOFWEEK('2026-09-19') = 7   //// solo sabato
                THEN 'sab-scol'
    
                ELSE 'nessuna'
    
            END AS frequenza
    )
    
    ------------------------------------------sostituire con--------------------------------------------
    
    CASE
    
        WHEN DAYOFWEEK('2026-09-19') = 1
          OR EXISTS (
                SELECT 1
                FROM gbgar_festivita f
                WHERE f.GIORNO = '2026-09-19'
            )
        THEN 'festiva'
    
        WHEN DAYOFWEEK('2026-09-19') = 7
        THEN 'sab-scol'
    
        WHEN DAYOFWEEK('2026-09-19') BETWEEN 2 AND 6
        THEN 'scolastica'
    
        ELSE 'nessuna'
    
    END AS frequenza
    
    -------------------------------------------fine correzione------------------------------------------
    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;
  • Ok. esisteva un errore logico.

    questa query però non riesce a prelevare tutti i casi che servono:

    facendo una prova per una data come ad es. il sabato 19-09-2026,

    prende solo la corsa della tabella giornaliera e solo quella della tabella con frequenza lun-ven-scol ignorando che cmq vanno prese, in questo caso anche quelle con frequenza scolastica che sono valide tutti i giorni feriali invernali compreso il sabato.

    Ho fatto anche io diverse prove ma non riuscivo a trovare la soluzione.
    Quindi mi son andato a ripassare cosa servono le "union all" perché a sto punto, qualche cosa che non ricordo esattamente e che non ho semplicemente capito ci deve essere.

    Con l'aiuto dell'AI, che mi stava mettendo un po fuori strada, a forza di tentativi ho raggiunto quanto segue.

    SET @giorno_servizio='2026-09-19';
    
    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 @giorno_servizio 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
    ),
    
    -- Mappatura dinamica di tutte le frequenze valide per il giorno di servizio
    
    giorno_frequenze AS (
        SELECT 'giornaliera' AS frequenza -- Valida sempre, per qualsiasi giorno
        
        UNION ALL
        
        SELECT 
            CASE 
                -- SE È FESTIVO (Domenica o Tabella Festività)
                WHEN DAYOFWEEK(@giorno_servizio) = 1
                  OR EXISTS (SELECT 1 FROM gbgar_festivita f WHERE f.GIORNO = @giorno_servizio)
                THEN 'festiva'
                
                -- SE È SABATO
                WHEN DAYOFWEEK(@giorno_servizio) = 7 
                THEN 'sabato'
                
                -- SE È LUNEDÌ-VENERDÌ
                ELSE 'feriale'
            END AS frequenza
    
        UNION ALL
    
        -- Aggiungiamo le frequenze specifiche richieste per il periodo invernale scolastico
        
        SELECT 'scolastica' AS frequenza WHERE DAYOFWEEK(@giorno_servizio) BETWEEN 2 AND 7
        
        UNION ALL
        
        SELECT 'sab-scol' AS frequenza WHERE DAYOFWEEK(@giorno_servizio) = 7
        
        UNION ALL
        
        SELECT 'lun-ven-scol' AS frequenza WHERE DAYOFWEEK(@giorno_servizio) BETWEEN 2 AND 6
        
        UNION ALL
        SELECT 'sab-scol' AS frequenza 
        WHERE DAYOFWEEK(@giorno_servizio) BETWEEN 2 AND 6
    )
    
    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,
        tm.FREQUENZA AS frequenza_tabella
    
    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
    -- Sostituiamo il CROSS JOIN con un INNER JOIN sulla tabella delle frequenze ammesse
    INNER JOIN giorno_frequenze gf ON tm.FREQUENZA = gf.frequenza
    
    WHERE
        tm.PERIODO = p.periodo
    
    ORDER BY
        c.ORARIO_CORSA;
    

    Insomma, chiedo scusa ma non riuscivo a vedere il quadro della situazione.
    Quindi poi ho capito che in pratica le union all servono eccome e alla fine il tutto me lo spiego cosi:

    WITH: apre una tabella provvisoria che si chiama"periodo" (ho scoperto che sono definite CTE).
    e poi AS per istruire cosa deve rappresentare questa CTE, cioè cosa deve contenere.
    Al suo interno prelevo i dati da una tabella fisica con una subquery praticamente, una select insomma sulla tabella fisica gbgar_periodi che funge da tabella sorgente in questo blocco. 
    Prelevo la colonna sorgente 'descrizione_periodo'
    Nel tempo stesso dentro la select si pongono 4 casi (assomiglia allo swich di php), corrispondenti ai record della tabella fisica sorgente e pone 4 espressioni relative da inserire nella colonna 'periodi', della CTE aperta.
    E' un po' strano il fatto che il nome della colonna 'periodo' in questa CTE, venga assegnato in chiusura 
    (END AS periodo), ci ho messo un po' a intuire che a livello di sintassi, prima si creano le condizioni per stabilire il valore potenziale e poi si chiude il CASE assegnando il nome alla colonna. 
    Poi, 
    Siccome la tabella provvisoria 'periodi' deve prelevare un solo periodo a seconda del valore di @giorno_servizio settato inizialmente (che in php poi sarà rappresentato da $data_servizio),
    fa un controllo nella WHERE per prelevare il record sorgente che comprende tra le sue date (data_inizio e data_fine) il valore di @giorno_servizio.

    Siccome però il periodo pasquale e natalizio sono inglobate nel periodo compreso tra le date del periodo invernale è necessario ordinare una priorità tra i periodi, e limitare il prelevamento al primo periodo che ha corrispondenza.   
    Qua si chiude la prima CTE.

    Niente UNION ALL qui visto che questa viene agganciata con una CROSS JOIN nella select finale.

    Poi viene creata un' altra CTE che  si chiama giorno_frequenze.

    Prelevando il blocco a se stante, e provandolo in console sql, vedo che questa tabella ha una sola colonna : 'frequenza'.

    in questa convogliano i valori di 5 UNION ALL.

    E finalmente ho capito cosa si intende per union all. Avevo capito servisse per unire record di tabelle diverse in una sola tabella ma con la clausola che ci fosse compatibilità tra i campi delle tabelle sorgenti, vale a dire stesso numero di colonne e valori compatibili. (int, char ..... quello che è) .
    Dal momento che la tabella che raccoglie i dati è una CTE creata ad arte diciamo, per forza che i campi son compatibili, visto che creandola vado a prender i dati che possono essere uniti.

    Quindi:
     1° valore: 'giornaliera'  
    che serve per le corse delle tabelle di marcia che nella tabella sql sorgente (gbgar_tab_marcia), hanno quel valore nel campo "frequenza".

    poi la prima UNION ALL, e ci metto:

    valore: 'festivo', 'sabato', 'feriale'
    ricavato dal calcolo della funzione DAYOFWEEK (@giorno_servizio), impostando nella sua SELECT una condizione (CASE) per cui ottengo uno dei tre potenziali valori.

    Poi le seguenti UNION ALL per avere tutti i valori possibili da incrociare con periodi:

    'scolastica' per i gg da 1 a 7 (lun-sab),
    'sab-scol'  per i gg =7 (sabato),
    'lun-ven-scol' per i gg da 1 a 6  (da lun a ven),
    di nuovo 'sab-scol' ma stavolta anche per i gg da 1 a 6.

    Quindi ho tutti i valori coincidenti con i valori ammessi da gbgar_tab_marcia.frequenza.

    La select finale:

    -prende i valori elencati  in select 
    -imposta le 2 join su gbgar_fermate per avere i nomi delle fermate,
    -imposta la join con la tabella gbgar_tab_marcia indispensabile per college le corse alle tabelle che vengono selezionate a monte.
    -CROSS join con la CTE 'periodi' e INNER JOIN con l'altra CTE 'giorno-frequenze' per collegare ogni voce potenziale delle due CTE.

    tutta una giornata per arrivare qua, devo ora integrare il tutto nel file select_corse.php, sostituendo lo script attuale con questa unica grande select.

    Aggiorno sulla riuscita finale ma in teoria devo solo inserire la variable $data_servizio come parametro al posto di @giorno_servizio usato per questi test in sql.

    Aggiungere la clausola AND EXIST ... per sottrarre alla select finale gli id_corsa già registrati per la stesa data in gbgar_serv_detail. (prima di order by c.ORARIO_CORSA).

    inserire il tutto come di consueto in una variabile php ed eseguirla per ottenere la mia lista in $corse_da_svolgere quotidianamente e in coerenza dinamica col tipo di periodo e giorno di riferimento.

    Buona giornata e grazie di tutto.

    Filippo.  

  • Quindi hai risolto?

Devi accedere o registrarti per scrivere nel forum
76 risposte