View Full Version : [MySql]Aiutino per una View
RaouL_BennetH
02-01-2008, 13:47
Ciao a tutti :)
Ho una tabella così composta:
ID_Mese;
ID_Dipendente;
giorno;
base;
differenza;
totale;
//contenente valori del tipo:
ID_Mese = 1;
ID_Dipendente = 23;
giorno = 01;
base = 5.50;
variazione = 0;
differenza = 0;
//oppure per un giorno diverso:
ID_Mese = 1;
ID_Dipendente = 23;
giorno = 02;
base = 5.50;
variazione = 3.50
differenza = -2.00;
Ora, avrei bisogno di estrapolare da questa tabella di base una rappresentazione del tipo:
ID_Dipendente -- 01 -- 02 -- 03 -- 04 -- (etc.. sono i giorni del mese)
23 5.50 <- base
23 0.00 <- variazione
23 0.00 <- differenza
5.50 <- base
3.50 <-variazione
-2.00 <- differenza
*Solo per chiarezza sono su righe diverse, in realtà questa vista dovrebbe avere 3 righe per ogni dipendente.
Come potrei fare?
Grazie mille :)
RaouL.
Per avere tre righe per ogni utente basta fare una UNION associando ai vari campi lo stesso nome.
(SELECT ID, Base AS Dato From Tabella)
UNION
(SELECT ID, Diffrenza AS Dato From Tabella)
UNION
(SELECT ID, Varianza AS Dato From Tabella)
RaouL_BennetH
07-01-2008, 10:40
Per avere tre righe per ogni utente basta fare una UNION associando ai vari campi lo stesso nome.
(SELECT ID, Base AS Dato From Tabella)
UNION
(SELECT ID, Diffrenza AS Dato From Tabella)
UNION
(SELECT ID, Varianza AS Dato From Tabella)
Grazie mille :) E' perfetto.
RaouL_BennetH
07-02-2008, 12:37
Inizio ad avere problemi con queste union.
Fin quando mi limito ad un solo giorno, va bene, ma se i giorni sono più di uno, oppure durante uno stesso giorno ci sono state più lavorazioni non ne vengo fuori :(
Ad esempio, il tipo di visualizzazione che io dovrei ricavare dovrebbe essere così:
ID_Dipendente giorno1 giorno2 giorno3
1 5 5 5
1 0 3 6
1 0 -2 1
la tabella dove sono presenti questi dati contiene:
ID_Mese
ID_Dipendente
ParametroBase
OreLavorate
DifferenzaDaParametroBase
ID_Dipendente giorno1 giorno2 giorno3
1 5 5 5
1 0 3 6
1 0 -2 1
Una visualizzazione di quel tipo la puoi imho ottenere solo elaborando i dati successivamente.
Quello che puoi ottenere è questo:
ID_Dipendente giorno base differenza varianza
1 1 5 0 0
1 2 5 3 -2
1 3 5 6 1
RaouL_BennetH
07-02-2008, 15:38
al momento ho arzigogolato così creandomi una vista con un'altra tabella
SELECT codicelavoro, 'counter' as 'dayCounter' from PIfeb_2008
union
select codicelavoro, parbase from oredelta WHERE (select substring("dayCounter", 4) = oredelta.giorno)
union
select oredelta.codicelavoro, (PIfeb_2008.sab2 - oredelta.parbase) from PIfeb_2008, oredelta where (select substring("dayCounter", 4) = oredelta.giorno)
//inserito in un for
//è piuttosto lento ma almeno inizio ad avere il tipo di visualizzazione che mi serve
Appunto...inserito in un for ;)
In ogni caso con una query molto semplice puoi ottenere il risultato che ti ho scritto e riprendere i dati pari pari.
RaouL_BennetH
07-02-2008, 16:14
Appunto...inserito in un for ;)
In ogni caso con una query molto semplice puoi ottenere il risultato che ti ho scritto e riprendere i dati pari pari.
Ecco, sul for .... :
considerando che le tabelle sono due:
PIfeb_2008 e oredelta
try
{
int days = Thread.CurrentThread.CurrentCulture.Calendar.GetDaysInMonth(2008, 2);
string[] g = new string[days];
string select = "SELECT codicelavoro ";
for(int count = 1; count <= days; ++count)
{
DateTime dt = new DateTime(2008, 2, count);
g[days -1] = dt.ToString("ddd");
s += ", '" + g[days -1 ] + count + "' AS giorno "
//considerando la query che ho tirato fuori nel post precedente... come posso continuare qui?!?
}
Grazie :)
RaouL.
Non ho ben capito quale sia il problema e cosa vuoi fare... :D
RaouL_BennetH
07-02-2008, 16:36
Non ho ben capito quale sia il problema e cosa vuoi fare... :D
Hai ragione :)
Allora, la query che utilizzo in mysql e funziona (per un giorno per volta però) è:
SELECT codicelavoro, sab2 as giorno from PIfeb_2008
union
select codicelavoro, parbase from oredelta WHERE (select substring("sab2", 4) = oredelta.giorno)
union
select oredelta.codicelavoro, (PIfeb_2008.sab2 - oredelta.parbase) from PIfeb_2008, oredelta where (select substring("sab2", 4) = oredelta.giorno)
ora, passando al codice dell'applicazione, e considerando le due tabelle:
PIfeb_2008 che ha come colonne:
codicelavoro
ven1
sab2
dom3
lun4
etc...
mentre invece oredelta ha come colonne:
codicelavoro
giorno
parbase
facendo la query da mysql come mi hai suggerito tu per le union, io non faccio altro che prendere il valore contenuto in "ven1", per esempio "8.00";
dato che in oredelta i giorni sono memorizzati con il numero e non con il nome, per esempio: giorno = 1, confronto solo le sottostringhe e mi ricavo il parametrobase da oredelta(per esempio 9.00)
Con la query di sopra, lui giorno per giorno prende le ore lavorate, le confronta con quelle del parametro e mi dice se ci sono differenze oppure no.
Nell'applicazione uso il datetime per ricavarmi il nome dei giorni per oredelta, in modo da poter applicare la query.
Quello che non riesco a fare, è ovviamente mettere il tutto nel "for" :(
PIfeb_2008 che ha come colonne:
codicelavoro
ven1
sab2
dom3
lun4
etc...
Chi l'ha progettata questa tabella ??? Chi l'ha scritta dovrebbe farsi una bella ripassata alle regole basi dei DBMS :D
Una cattiva base dati ti porta a creare cattivo codice ;)
RaouL_BennetH
07-02-2008, 16:48
PIfeb_2008 che ha come colonne:
codicelavoro
ven1
sab2
dom3
lun4
etc...
Chi l'ha progettata questa tabella ??? Chi l'ha scritta dovrebbe farsi una bella ripassata alle regole basi dei DBMS :D
Una cattiva base dati ti porta a creare cattivo codice ;)
Non ne ho la più pallida idea sinceramente.
Io purtroppo al database non posso apportare cambi di mia iniziativa :(
La tabella però viene creata a run-time dal programma, in base ad una notevole quantità di variabili.
E' veramente una tabella assurda :muro: :muro:
Non fare più la union, non conviene.
Fai semplicemente una query:
SELECT *, substring(oredelta.giorno, 4) AS ordine FROM oredelta JOIN PIfeb_2008 ON oredelta.codicelavoro = PIfeb_2008.codicelavoro ORDER BY ordine ASC;
A questo punto semplicemente ti scorri i risultati, ti ricavi giorno e lo usi per indicizzare la colonna. A quel punto fai la differenza fra parbase e quello scritto nella rispettiva colonna.
RaouL_BennetH
08-02-2008, 15:50
E' veramente una tabella assurda :muro: :muro:
Non fare più la union, non conviene.
Fai semplicemente una query:
SELECT *, substring(oredelta.giorno, 4) AS ordine FROM oredelta JOIN PIfeb_2008 ON oredelta.codicelavoro = PIfeb_2008.codicelavoro ORDER BY ordine ASC;
A questo punto semplicemente ti scorri i risultati, ti ricavi giorno e lo usi per indicizzare la colonna. A quel punto fai la differenza fra parbase e quello scritto nella rispettiva colonna.
Ho provato a fare così, ma non capisco poi i risultati della query e come potrei manipolarli, nel senso che dovrei comunque fare altre query per arrivare al risultato desiderato :help:
Assolutamente no...basta fare le differenze tramite codice.
Posta un po' quello che viene fuori dalla query con dei dati di esempio.
RaouL_BennetH
08-02-2008, 16:59
Assolutamente no...basta fare le differenze tramite codice.
Posta un po' quello che viene fuori dalla query con dei dati di esempio.
ok questa è la query:
SELECT *, substring("ven1", 4) AS ordine FROM PIfeb_2008
JOIN
oredelta ON PIfeb_2008.codicelavoro = oredelta.codicelavoro ORDER BY ordine ASC;
e questo è il risultato:
codicelavoro ven1 sab2 codicelavoro giorno parbase ordine
6999 8 6 6999 1 8 1
6999 8 6 6999 2 12 1
6999 8 6 6999 3 9 1
Togli pure "substring("ven1", 4) As ordine" (al posto di "ven1" ci doveva essere oredelta.giorno) tanto mi sembra che giorno sia solo un numero e non il giorno espresso a lettere e numeri. Aggiungi un "ORDER BY giorno".
Fammi capire...al giorno 1 è sempre associato ven, al giorno 2 sab e così via oppure possono cambiare ?
Se sono fissi (mi sembra che tu li stia ricavando dal mese):
Recordset rs = faiQuery(query);
do
{
day = rs.get("giorno");
DateTime dt = new DateTime(2008, 2, day);
string dayField = dt.ToString("ddd") + string.ToString(day);
hours.add(day, rs.get(dayField));
bases.add(day, rs.get("parbase"));
diffs.add(day, rs.get("parbase") - rs.get(dayField));
rs.moveNext();
}
while(rs.hasNext());
Nota che non so assolutamente niente di C#. Ci capisci ? hours, bases e diffs sono delle collection associative con ore, base e differenza.
RaouL_BennetH
09-02-2008, 10:43
Fammi capire...al giorno 1 è sempre associato ven, al giorno 2 sab e così via oppure possono cambiare ?
Cambiano in base al mese scelto. In pratica succede questo:
In una schermata l'utente sceglie il mese di lavoro, viene creata una griglia che contiene il codice lavoro del dipendente, e poi, tante colonne per quanti sono i giorni del mese scelto. Ma questo solo per l'elaborazione mensile finale.
Se sono fissi (mi sembra che tu li stia ricavando dal mese):
Recordset rs = faiQuery(query);
do
{
day = rs.get("giorno");
DateTime dt = new DateTime(2008, 2, day);
string dayField = dt.ToString("ddd") + string.ToString(day);
hours.add(day, rs.get(dayField));
bases.add(day, rs.get("parbase"));
diffs.add(day, rs.get("parbase") - rs.get(dayField));
rs.moveNext();
}
while(rs.hasNext());
Nota che non so assolutamente niente di C#. Ci capisci ? hours, bases e diffs sono delle collection associative con ore, base e differenza.
[/quote]
uhm.. devo cercare di capire qual'è l'equivalente di un recordset in C#.
Ma poi, tralasciando per un secondo l'orrore del mio codice, almeno per cercare di tirare fuori il risultato desiderato, e poi andare a raffinare la soluzione, ieri ero riuscito a fare questo (considerando il tuo suggerimento delle union)
int days = Thread.CurrentThread.CurrentCulture.Calendar.GetDaysInMonth(2008, 2);
string[] g = new string[days];
string s = "SELECT codicelavoro ";
for(int count = 1; coun <= days; ++count)
{
//codice che mi legge dalla tabella i vari "nomeGiornoNumeroGiorno"
DateTime dt = new DateTime(2008, 2, count);
g[days - 1] = dt.ToString("ddd");
s += ", " + g[days - 1] + count + " AS 'giorno' ";
}
s += "FROM PIfeb_2008 UNION SELECT codicelavoro ";
//qui dovrei aggiungere un altro for per scorrere i "parametroBase" dalla tabella oredelta
for(int count = 1; count <= days; ++count)
{
s += ", parbase AS 'giorno' ";
}
s += "FROM oredelta ";
//senza considerare ancora di fare la differenza fra i valori di base e gli effettivi.
Questo codice però, mi mostra correttamente i valori contenuti in PIfeb_2008, ma non quelli di oredelta, nel senso che ottengo:
codicelavoro-----giorno-----giorno1-----giorno2-----giorno3
6999 5 5 7
6999 8 8 8 8 8 8
6999 6 6 6 6 6 6
Cioè:
la prima riga è corretta e la legge da PIfeb_2008 e dove non ci sono valori, è vuota
La seconda e terza riga invece, sono completamente errate, perchè riporta il valore in tutti i giorni, nel senso che il risultato avrebbe dovuto invece essere:
codicelavoro-----giorno-----giorno2
6999 5 5
6999 8 6
P.S.: Ma c'è modo di formattare le tabelle?!?!?
Cambiano in base al mese scelto. In pratica succede questo:
In una schermata l'utente sceglie il mese di lavoro, viene creata una griglia che contiene il codice lavoro del dipendente, e poi, tante colonne per quanti sono i giorni del mese scelto. Ma questo solo per l'elaborazione mensile finale.
Un recordset è un insieme di record...è il risultato di una query.
Comunque ho guardato e te la adatto:
foreach (DataRow myDataRow in myDataTable.Rows)
{
day = myDataRow["giorno"];
DateTime dt = new DateTime(2008, 2, day);
string dayField = dt.ToString("ddd") + string.ToString(day);
hours.add(day, myDataRow[dayField]);
bases.add(day, myDataRow["parbase"]);
diffs.add(day, myDataRow["parBase"] - myDataRow[dayField]);
}
RaouL_BennetH
09-02-2008, 11:40
Perdonami :muro:
Ma non riesco a capire il codice :cry:
Allora:
try
{
int days = GetDaysInMonth(2008, 2);
DbClass db = new DbClass();
db.OpenConnection();
string s = "SELECT *, giorno FROM oredelta " +
"JOIN " +
"PIfeb_2008 ON oredelta.codicelavoro = PIfeb_2008.codicelavoro ORDER BY giorno ASC ";
MySqlDataAdapter mda = new MySqlDataAdapter(select, db.ActiveConnection);
DataTable dt = new DataTable();
mda.Fill(dt);
foreach(DataRow r in dt.Rows)
{
//non riesco ad adattare il codice
}
Scusa, ma cosa non ti torna ?
RaouL_BennetH
09-02-2008, 12:00
Scusa, ma cosa non ti torna ?
questo è il tuo codice:
foreach (DataRow myDataRow in myDataTable.Rows)
{
day = myDataRow["giorno"]; <- day che tipo di variabile è ?!?
DateTime dt = new DateTime(2008, 2, day);
string dayField = dt.ToString("ddd") + string.ToString(day); <- "string.ToString" a quale string si riferisce?
hours.add(day, myDataRow[dayField]);
bases.add(day, myDataRow["parbase"]);
diffs.add(day, myDataRow["parBase"] - myDataRow[dayField]);
}
hours, bases e diffs sono tipi datetime ?
Grazie :)
Come ti ho detto non conosco il C#. Non so come si converte un intero a stringa...
string dayField = dt.ToString("ddd") + string.ToString(day);
In pratica l'intenzione era convertire day in stringa.
hours, bases e diffs sono tipi datetime ? No sono collection associative. Map, Set o qualsiasi altra cosa.
RaouL_BennetH
09-02-2008, 12:51
Come ti ho detto non conosco il C#. Non so come si converte un intero a stringa...
string dayField = dt.ToString("ddd") + string.ToString(day);
In pratica l'intenzione era convertire day in stringa.
hours, bases e diffs sono tipi datetime ? No sono collection associative. Map, Set o qualsiasi altra cosa.
Ah ecco, allora è per questo che non capisco. Non sono ancora arrivato a studiare le collection.
Potremmo fare un salto indietro?
Nel senso:
SELECT codicelavoro, sab2 as giorno from PIfeb_2008
union
select codicelavoro, parbase from oredelta WHERE (select substring("sab2", 4) = oredelta.giorno)
union
select oredelta.codicelavoro, (PIfeb_2008.sab2 - oredelta.parbase) from PIfeb_2008, oredelta where (select substring("sab2", 4) = oredelta.giorno)
dato che riesco a ricavarmi i vari "ven1", "sab2", etc... come potrei ciclarla questa query ?
Grazie mille :)
RaouL.
No...non facciamo un salto indietro. E' problematico gestire la cosa con le union.
Cosa ci vuoi fare con quei dati ? Li vuoi stampare ? Dove li vuoi mettere questi dati ? Fammi un esempio, avendo a disposizione giorno, ore, base e differenza,
RaouL_BennetH
09-02-2008, 13:09
No...non facciamo un salto indietro. E' problematico gestire la cosa con le union.
Cosa ci vuoi fare con quei dati ? Li vuoi stampare ? Dove li vuoi mettere questi dati ? Fammi un esempio, avendo a disposizione giorno, ore, base e differenza,
Ok. Questi dati devono andare in una griglia (datagridview).
Per ottenerli l'utente fa queste operazioni:
il primo inserimento avviene nella tabella "oredelta", per esempio, supposto che il codice lavoro sia 10, l'inserimento sarà:
codicelavoro = 10
giorno = 1
parametroBase = 5.00
oreLavorate = 5.00
differenzaParametro = 0.00
------
codicelavoro = 10
giorno = 2
parametroBase = 5.00
oreLavorate = 4.00
differenzaParametro = -1.00
------
In una seconda fase, cioè alla fine del mese, l'utente deve creare la tabella relativa al lavorato mensile delle persone, quindi sceglie un codice di reparto (per esempio PI) il mese di lavoro e l'anno(feb_2008) e crea la tabella:
PIfeb_2008 che comunque risulta popolata da una select su oredelta.
a questo punto deve avere una visualizzazione di questo tipo:
codicelavoro nomeGiornoNumeroGiorno -- nomeGiornoNumeroGiorno -- blabla
per ciascun lavoratore devono esserci 3 righe:
per esempio:
10 -- 5.00 -- 5.00
10 -- 5.00 -- 4.00
10 -- 0.00 -- -1.00
Nelle due tabelle "codicelavoro" è la chiave primaria ma mentre oredelta ha una struttura fissa, l'altra tabella e il nome della stessa cambia per il reparto di lavoro e per il mese, per esempio si avranno tabelle come:
PIfeb_2008, HJfeb_2008 etc... ma non è un problema ricavarne il nome.
in genere io faccio sempre le query con il db, e poi uso gli oggetti a disposizione del programma per la visualizzazione, per esempio:
string select = "SELECT * FROM tabella";
MySqlDataAdapter adapter = new MySqlDataAdapter(select, connessione);
DataTable dt = new DataTable();
adapter.Fill(dt);
miaGriglia.DataSource = dt;
//in questo modo visualizzo tutti i risultati ottenuti dalla select
In questo caso non puoi aggiungerli tutti assieme visto che vanno elaborati. Fammi vedere come li aggiungi i dati singolarmente alla grid.
RaouL_BennetH
09-02-2008, 13:22
In questo caso non puoi aggiungerli tutti assieme visto che vanno elaborati. Fammi vedere come li aggiungi i dati singolarmente alla grid.
Riesco a farlo solo per quanto riguarda PIfeb_2008:
try
{
int giorni = GetDaysInMonth(2008, 2);
string[] nomeGiorno = new string[giorni];
//apro la connessione
DbClass db = new DbClass();
db.OpenConnection();
string select = "SELECT codicelavoro ";
for(int count = 1; count <= giorni; ++count)
{
//ricavo il nome delle colonne della tabella che sono nome e numero
//giorni del mese
DateTime dt = new DateTime(2008, 2, giorni);
nomeGiorno[giorni - 1] = dt.ToString("ddd");
select += ", " + nomeGiorno[giorni - 1 ] + count + " ";
}
select += "FROM PIfeb_2008";
MySqlDataAdatper adapter = new MySqlDataAdapter(select, db.ActiveConn);
DataTable myTable = new DataTable();
adapter.Fill(myTable);
myGrid.DataSource = myTable;
myGrid.AutoGenerateColumns = true;
db.ClseConnection(db.ActiveConn);
}
catch(MySqlException ex)
{
MessageBox.Show(ex.Message);
}
e ottengo la visualizzazione completa del contenuto di PIfeb_2008
Parlaimo e nun ce capaimo...come diceva un comico di Mai Dire Gol...
Non puoi passare direttamente il DataTable come sorgente della grid perché i dati recuperati vanno rielaborati !!!
Metti di avere a disposizione:
string day;
int hour;
int base;
int diff;
e metti che tu li voglia visualizzare solo su una riga in una grid...come si fa ?
RaouL_BennetH
09-02-2008, 13:42
Parlaimo e nun ce capaimo...come diceva un comico di Mai Dire Gol...
Non puoi passare direttamente il DataTable come sorgente della grid perché i dati recuperati vanno rielaborati !!!
Metti di avere a disposizione:
string day;
int hour;
int base;
int diff;
e metti che tu li voglia visualizzare solo su una riga in una grid...come si fa ?
:doh:
scusami !!
così diventa molto complicato (per me) perchè la griglia si deve comporre "a mano", nel senso che ci sarebbero due modi:
1) La via più semplice disegnarla con il designer dell'IDE, e impostare a priori nomi colonne e numero di righe, e poi semplicemente andare a dire per ogni cella della riga quale valore assegnare (day, hours, base etc...) Ma questo si potrebbe fare solo nel caso che a priori io sappia da quante colonne può essere formata la griglia.
2) Costruirla via codice:
//solo per le colonne ad esempio
DataGridViewColumn[] column = new DataGridViewColumn[days];
column[0].HeaderText = days1 ; //esempio, ma si dovrebbe ciclare
//e fare la stessa cose per le righe con la complicazione di andare a dire
//per ogni cella quale valore assegnare e dove prenderselo, per esempio:
DataGridViewRow r = new DataGridViewRow();
r.Cells[0].Value = "codicelavoro";
r.Cells[1].Value = "ven1";
r.Cells[2].Value = "sab2";
//etc...
this.myGrid.Columns.AddRange(column);
this.myGrid.Rows.Count = 1;
E' proprio quello che devi andare a fare...
Dopo per ogni ciclo del for generi un riga.
In alternativa c'è la possibilità di andare a complicare di molto la query...come dipende dal tipo di dbms e dagli strumenti che mette a disposizione.
RaouL_BennetH
12-02-2008, 13:11
EDIT
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.