/ Forside / Teknologi / Udvikling / SQL / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
SQL
#NavnPoint
pmbruun 1704
niller 962
fehaar 730
Interkril.. 701
ellebye 510
pawel 510
rpje 405
pete 350
gibson 320
10  smorch 260
NULL
Fra : Carsten Bager


Dato : 22-07-07 16:05

Her er en stump kode hvor jeg finder records hvor dato og navn passer, og skriver resultatet i en ny tabel.
Det virker fint. Nu har jeg det problem at hvis der ikke findes en record så skrives der NULL i time felterne.
Det prøver jeg så at forhindre ved at teste om de er NULL, hvis ja så indsætte en værdi.
Det virker ikke, der står stadig NULL i time felterne i de records hvor der ikke var et hit.
Er der et forslag til hvordan jeg løser dette problem.

Carsten
(En nybegynder i MYSQL)


SELECT SUM(Timer),SUM(Time_sats_1),SUM(Time_sats_2),SUM(Time_sats_3) INTO vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer FROM timesedler WHERE (DATE(vDatoS) = DATE(dato)) AND Bruger = Bruger_navn;
# Gem i resultater MaanedsTabel
IF (vNormalTimer = NULL) THEN
SET vNormalTimer = '0.00';
END IF;
IF (vSats1Timer = NULL) THEN
SET vSats1Timer = '0.00';
END IF;
IF (vSats2Timer = NULL) THEN
SET vSats2Timer = '0.00';
END IF;
IF (vSats3Timer = NULL) THEN
SET vSats3Timer = '0.00';
END IF;
INSERT INTO MaanedsTabel (Dato, Bruger_navn, Timer, Time_sats_1,Time_sats_2, Time_sats_3) VALUES (vDatoS,Bruger,vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer);

 
 
Gert Krabsen (22-07-2007)
Kommentar
Fra : Gert Krabsen


Dato : 22-07-07 17:40

Carsten Bager wrote:
> Her er en stump kode hvor jeg finder records hvor dato og navn passer,
> og skriver resultatet i en ny tabel.
> Det virker fint. Nu har jeg det problem at hvis der ikke findes en
> record så skrives der NULL i time felterne.
> Det prøver jeg så at forhindre ved at teste om de er NULL, hvis ja så
> indsætte en værdi.
> Det virker ikke, der står stadig NULL i time felterne i de records hvor
> der ikke var et hit.
> Er der et forslag til hvordan jeg løser dette problem.


Der er en række usammenhængende ting i din kode. Men for at kunne give
et fornuftigt svar er vi nødt til at vide, hvilket programmeringssprog
du har i brug.



Kaj Julius (22-07-2007)
Kommentar
Fra : Kaj Julius


Dato : 22-07-07 18:37


"Carsten Bager" <rosenalleNOMAIL@mail.dk> skrev i en meddelelse
news:46a3722a$0$13234$edfadb0f@dread14.news.tele.dk...
> Her er en stump kode hvor jeg finder records hvor dato og navn passer, og
> skriver resultatet i en ny tabel.
> Det virker fint. Nu har jeg det problem at hvis der ikke findes en record
> så skrives der NULL i time felterne.
> Det prøver jeg så at forhindre ved at teste om de er NULL, hvis ja så
> indsætte en værdi.
> Det virker ikke, der står stadig NULL i time felterne i de records hvor
> der ikke var et hit.
> Er der et forslag til hvordan jeg løser dette problem.
>
> Carsten
> (En nybegynder i MYSQL)
>
>
> SELECT SUM(Timer),SUM(Time_sats_1),SUM(Time_sats_2),SUM(Time_sats_3)
> INTO vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer FROM timesedler
> WHERE (DATE(vDatoS) = DATE(dato)) AND Bruger = Bruger_navn;
> # Gem i resultater MaanedsTabel
> IF (vNormalTimer = NULL) THEN
> SET vNormalTimer = '0.00';
> END IF;
> IF (vSats1Timer = NULL) THEN
> SET vSats1Timer = '0.00';
> END IF;
> IF (vSats2Timer = NULL) THEN
> SET vSats2Timer = '0.00';
> END IF;
> IF (vSats3Timer = NULL) THEN
> SET vSats3Timer = '0.00';
> END IF;
> INSERT INTO MaanedsTabel (Dato, Bruger_navn, Timer,
> Time_sats_1,Time_sats_2, Time_sats_3) VALUES
> (vDatoS,Bruger,vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer);

Det nemmeste vil være at lade SQL foretage konverteringen af NULL til 0. Det
kan bl.a. gøres med funktionen COALESCE:

SELECT SUM(COALESCE(Timer,
0)),SUM(COALESCE(Time_sats_1,0)),SUM(COALESCE(Time_sats_2,0)),SUM(COALESCE(Time_sats_3,0))
INTO vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer FROM timesedler WHERE
(DATE(vDatoS) = DATE(dato)) AND Bruger = Bruger_navn;

Så er der ikke brug for en efterfølgende konvertering i din kode.



Kaj Julius (22-07-2007)
Kommentar
Fra : Kaj Julius


Dato : 22-07-07 18:52


"Kaj Julius" <Xxxxx@forsvindiledespammere.dk> skrev i en meddelelse
news:46a395bc$0$850$edfadb0f@dread12.news.tele.dk...
>
> "Carsten Bager" <rosenalleNOMAIL@mail.dk> skrev i en meddelelse
> news:46a3722a$0$13234$edfadb0f@dread14.news.tele.dk...
>> Her er en stump kode hvor jeg finder records hvor dato og navn passer, og
>> skriver resultatet i en ny tabel.
>> Det virker fint. Nu har jeg det problem at hvis der ikke findes en record
>> så skrives der NULL i time felterne.
>> Det prøver jeg så at forhindre ved at teste om de er NULL, hvis ja så
>> indsætte en værdi.
>> Det virker ikke, der står stadig NULL i time felterne i de records hvor
>> der ikke var et hit.
>> Er der et forslag til hvordan jeg løser dette problem.
>>
>> Carsten
>> (En nybegynder i MYSQL)
>>
>>
>> SELECT SUM(Timer),SUM(Time_sats_1),SUM(Time_sats_2),SUM(Time_sats_3)
>> INTO vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer FROM timesedler
>> WHERE (DATE(vDatoS) = DATE(dato)) AND Bruger = Bruger_navn;
>> # Gem i resultater MaanedsTabel
>> IF (vNormalTimer = NULL) THEN
>> SET vNormalTimer = '0.00';
>> END IF;
>> IF (vSats1Timer = NULL) THEN
>> SET vSats1Timer = '0.00';
>> END IF;
>> IF (vSats2Timer = NULL) THEN
>> SET vSats2Timer = '0.00';
>> END IF;
>> IF (vSats3Timer = NULL) THEN
>> SET vSats3Timer = '0.00';
>> END IF;
>> INSERT INTO MaanedsTabel (Dato, Bruger_navn, Timer,
>> Time_sats_1,Time_sats_2, Time_sats_3) VALUES
>> (vDatoS,Bruger,vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer);
>
> Det nemmeste vil være at lade SQL foretage konverteringen af NULL til 0.
> Det kan bl.a. gøres med funktionen COALESCE:
>
> SELECT SUM(COALESCE(Timer,
> 0)),SUM(COALESCE(Time_sats_1,0)),SUM(COALESCE(Time_sats_2,0)),SUM(COALESCE(Time_sats_3,0))
> INTO vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer FROM timesedler
> WHERE (DATE(vDatoS) = DATE(dato)) AND Bruger = Bruger_navn;
>
> Så er der ikke brug for en efterfølgende konvertering i din kode.
>
>

Hvis det viste er det eneste din kode gør, bør du kunne erstatte det med en
INSERT INTO direkte fra forespørgslen (med en GROUP BY på de to felter i
WHERE delen som skal med over i insert tabellen:

INSERT INTO MaanedsTabel (Dato, Bruger_navn, Timer, Time_sats_1,Time_sats_2,
Time_sats_3)
SELECT vDatoS, Bruger, SUM(COALESCE(Timer,
0)),SUM(COALESCE(Time_sats_1,0)),SUM(COALESCE(Time_sats_2,0)),SUM(COALESCE(Time_sats_3,0))
FROM timesedler
WHERE (DATE(vDatoS) = DATE(dato)) AND Bruger = Bruger_navn
GROUP BY vDatoS, Bruger;




Carsten Bager (24-07-2007)
Kommentar
Fra : Carsten Bager


Dato : 24-07-07 19:53

Kaj Julius wrote:
> "Carsten Bager" <rosenalleNOMAIL@mail.dk> skrev i en meddelelse
> news:46a3722a$0$13234$edfadb0f@dread14.news.tele.dk...
>> Her er en stump kode hvor jeg finder records hvor dato og navn passer, og
>> skriver resultatet i en ny tabel.
>> Det virker fint. Nu har jeg det problem at hvis der ikke findes en record
>> så skrives der NULL i time felterne.
>> Det prøver jeg så at forhindre ved at teste om de er NULL, hvis ja så
>> indsætte en værdi.
>> Det virker ikke, der står stadig NULL i time felterne i de records hvor
>> der ikke var et hit.
>> Er der et forslag til hvordan jeg løser dette problem.
>>
>> Carsten
>> (En nybegynder i MYSQL)
>>
>>
>> SELECT SUM(Timer),SUM(Time_sats_1),SUM(Time_sats_2),SUM(Time_sats_3)
>> INTO vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer FROM timesedler
>> WHERE (DATE(vDatoS) = DATE(dato)) AND Bruger = Bruger_navn;
>> # Gem i resultater MaanedsTabel
>> IF (vNormalTimer = NULL) THEN
>> SET vNormalTimer = '0.00';
>> END IF;
>> IF (vSats1Timer = NULL) THEN
>> SET vSats1Timer = '0.00';
>> END IF;
>> IF (vSats2Timer = NULL) THEN
>> SET vSats2Timer = '0.00';
>> END IF;
>> IF (vSats3Timer = NULL) THEN
>> SET vSats3Timer = '0.00';
>> END IF;
>> INSERT INTO MaanedsTabel (Dato, Bruger_navn, Timer,
>> Time_sats_1,Time_sats_2, Time_sats_3) VALUES
>> (vDatoS,Bruger,vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer);
>
> Det nemmeste vil være at lade SQL foretage konverteringen af NULL til 0. Det
> kan bl.a. gøres med funktionen COALESCE:
>
> SELECT SUM(COALESCE(Timer,
> 0)),SUM(COALESCE(Time_sats_1,0)),SUM(COALESCE(Time_sats_2,0)),SUM(COALESCE(Time_sats_3,0))
> INTO vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer FROM timesedler WHERE
> (DATE(vDatoS) = DATE(dato)) AND Bruger = Bruger_navn;

Tak for det. En lille finte var at der skal byttes rundt på SUM og COALESCE for at få det til at virke.
COALESCE(SUM(Time_sats_1),0)
Carsten
>
> Så er der ikke brug for en efterfølgende konvertering i din kode.
>
>

Carsten Bager (24-07-2007)
Kommentar
Fra : Carsten Bager


Dato : 24-07-07 20:08

Det jeg roder med er en proceduer som ser ud som følgende (MySQL 5).
Så langt virker det tilsyneladende fint, men jeg mangler stadig lidt arbejde.

Mvh

Carsten

----------------------------------------

CREATE DEFINER=`root`@`%` PROCEDURE `LavMaanedsSeddel`(IN MaanedsTabel char(40), IN Bruger char(40), IN Dt1 DateTime, IN Dt2 DateTime)
BEGIN
DECLARE maxrepeat int DEFAULT 0;
DECLARE vNormalTimer DECIMAL(19,2) DEFAULT 0;
DECLARE vSats1Timer DECIMAL(19,2) DEFAULT 0;
DECLARE vSats2Timer DECIMAL(19,2) DEFAULT 0;
DECLARE vSats3Timer DECIMAL(19,2) DEFAULT 0;
DECLARE vDatoS DATE;

# Slet tabel eller/og lav en ny


DROP TABLE IF EXISTS `maanedstabel`;
CREATE TABLE `maanedstabel` (
`Noegle` int(11) NOT NULL auto_increment,
`Dato` datetime default NULL,
`Timer` decimal(19,2) unsigned default '0.00',
`Time_sats_1` decimal(19,2) unsigned default '0.00',
`Time_sats_2` decimal(19,2) unsigned default '0.00',
`Time_sats_3` decimal(19,2) unsigned default '0.00',
`Bruger_navn` varchar(40) character set latin1 NOT NULL,
PRIMARY KEY (`Noegle`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_danish_ci COMMENT='InnoDB free: 4096 kB';

# Hent data og gem dem i tabel
# Set variabel dato = start dato
SET vDatoS = DATE(Dt1);
# Gennemsøg fra start til slut dato
REPEAT
# Find timer hvor dato og navn er OK
SELECT COALESCE(SUM(Timer),0),COALESCE(SUM(Time_sats_1),0),COALESCE(SUM(Time_sats_2),0),COALESCE(SUM(Time_sats_3),0) INTO vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer FROM timesedler WHERE
(DATE(vDatoS) = DATE(dato)) AND Bruger = Bruger_navn;
# Gem resultater i MaanedsTabel
INSERT INTO MaanedsTabel (Dato, Bruger_navn, Timer, Time_sats_1,Time_sats_2, Time_sats_3) VALUES (vDatoS,Bruger,vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer);
# Find næste dato
SET vDatoS = DATE_ADD(vDatoS,INTERVAL 1 DAY);
# Inc max søgninger
SET maxrepeat = maxrepeat + 1;
# Bliv ved indtil VdatoS = slut dato eller der er søgt i 400 dage
UNTIL (DATE(vDatoS) > DATE(Dt2)) or (maxrepeat > 400)
END REPEAT;
END

Kaj Julius (25-07-2007)
Kommentar
Fra : Kaj Julius


Dato : 25-07-07 18:19


"Carsten Bager" <rosenalleNOMAIL@mail.dk> skrev i en meddelelse
news:46a64e07$0$98084$edfadb0f@dread14.news.tele.dk...
> Det jeg roder med er en proceduer som ser ud som følgende (MySQL 5).
> Så langt virker det tilsyneladende fint, men jeg mangler stadig lidt
> arbejde.
>
> Mvh
>
> Carsten
>
> ----------------------------------------
>
> CREATE DEFINER=`root`@`%` PROCEDURE `LavMaanedsSeddel`(IN MaanedsTabel
> char(40), IN Bruger char(40), IN Dt1 DateTime, IN Dt2 DateTime)
> BEGIN
> DECLARE maxrepeat int DEFAULT 0;
> DECLARE vNormalTimer DECIMAL(19,2) DEFAULT 0;
> DECLARE vSats1Timer DECIMAL(19,2) DEFAULT 0;
> DECLARE vSats2Timer DECIMAL(19,2) DEFAULT 0;
> DECLARE vSats3Timer DECIMAL(19,2) DEFAULT 0;
> DECLARE vDatoS DATE;
>
> # Slet tabel eller/og lav en ny
>
>
> DROP TABLE IF EXISTS `maanedstabel`;
> CREATE TABLE `maanedstabel` (
> `Noegle` int(11) NOT NULL auto_increment,
> `Dato` datetime default NULL,
> `Timer` decimal(19,2) unsigned default '0.00',
> `Time_sats_1` decimal(19,2) unsigned default '0.00',
> `Time_sats_2` decimal(19,2) unsigned default '0.00',
> `Time_sats_3` decimal(19,2) unsigned default '0.00',
> `Bruger_navn` varchar(40) character set latin1 NOT NULL,
> PRIMARY KEY (`Noegle`)
> ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_danish_ci
> COMMENT='InnoDB free: 4096 kB';
>
> # Hent data og gem dem i tabel
> # Set variabel dato = start dato
> SET vDatoS = DATE(Dt1);
> # Gennemsøg fra start til slut dato
> REPEAT
> # Find timer hvor dato og navn er OK
> SELECT
> COALESCE(SUM(Timer),0),COALESCE(SUM(Time_sats_1),0),COALESCE(SUM(Time_sats_2),0),COALESCE(SUM(Time_sats_3),0)
> INTO vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer FROM timesedler
> WHERE (DATE(vDatoS) = DATE(dato)) AND Bruger = Bruger_navn;
> # Gem resultater i MaanedsTabel
> INSERT INTO MaanedsTabel (Dato, Bruger_navn, Timer,
> Time_sats_1,Time_sats_2, Time_sats_3) VALUES
> (vDatoS,Bruger,vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer);
> # Find næste dato
> SET vDatoS = DATE_ADD(vDatoS,INTERVAL 1 DAY);
> # Inc max søgninger
> SET maxrepeat = maxrepeat + 1;
> # Bliv ved indtil VdatoS = slut dato eller der er søgt i 400 dage
> UNTIL (DATE(vDatoS) > DATE(Dt2)) or (maxrepeat > 400)
> END REPEAT;
> END

Den metode du bruger til at opbygge din månedstabel er ikke den mest
optimale. Personligt ville jeg skynde mig at oprette en hjælpetabel med
datoer. Hvorfor nu det? Jo, for så undgår du det loop du nu er nødt til at
gennemføre. Det hele kan så stort set gennemføres i ét hug:

INSERT INTO MaanedsTabel (Dato, Bruger_navn, Timer, Time_sats_1,Time_sats_2,
Time_sats_3)
SELECT d.dato,
COALESCE(SUM(t.Timer),0),COALESCE(SUM(t.Time_sats_1),0),COALESCE(SUM(t.Time_sats_2),0),COALESCE(SUM(t.Time_sats_3),0)
INTO vNormalTimer,vSats1Timer,vSats2Timer,vSats3Timer
FROM datoer d
LEFT JOIN timesedler t ON d.dato = DATE(t.vDatoS)
WHERE d.dato BETWEEN DATE(dt1) AND DATE(dt2)
AND Bruger = Bruger_navn
GROUP BY d.dato;

Da støttetabellen indeholder alle datoer, kan man bruge den til at "fange"
også de datoer som ikke optræder i din tabel timesedler. Det gør det meget
lettere (og hurtigere) end at lave det som et loop i en stored procedure.

Forøvrigt behøver du ikke sidde og indtaste alle datoerne i støttetabellen i
hånden. Der er en udmærket måde hvorpå man kan gøre det meget hurtigt:

1) Opret en tabel som kun har et numerisk felt.
2) Indsæt værdierne 0 til 9 i denne tabel
3) Opret støttetabellen med datoerne (den skal bare indeholde et datofelt)
4) Udfør en ganske enkel INSERT INTO forespørgsel for at fylde den med
datoer:
INSERT INTO datoer
SELECT DATE_ADD('1980-01-01',INTERVAL
t1.Tal*1000+t2.Tal*100+t3.Tal*10+t4.Tal DAY)
FROM TalTabel t1, TalTabel t2, TalTabel t3,TalTabel t4;

Dette vil udløse, at der bliver oprettet 10000 datoer, startende fra den 1.
januar 1980. En sådan hjælpefil er dejlig at have ved hånden i mange
tilfælde.




Michael Zedeler (22-07-2007)
Kommentar
Fra : Michael Zedeler


Dato : 22-07-07 20:23

Carsten Bager wrote:
> [klip] # Gem i resultater MaanedsTabel
> IF (vNormalTimer = NULL) THEN
> SET vNormalTimer = '0.00';
> END IF; [klip]

Sådan undersøger man ikke om en værdi er NULL. Du skal skrive

vHormalTimer IS NULL

(...og IS NOT NULL for at undersøge om en værdi ikke er NULL.)

Mvh. Michael.

Søg
Reklame
Statistik
Spørgsmål : 177579
Tips : 31968
Nyheder : 719565
Indlæg : 6409073
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste