Op basis van een ellenlange (miljoenen records) tabel moet ik maandelijks een aantal records selecteren, en deze vervolgens in een CSV bestand steken met een aantal kolommen. De output hiervan ziet er zo uit:
De structuur van de basistabel is zo dat er gewoon geen structuur, sortering of normalisering aanwezig is.
De meetgegevens worden gewoon op een hoop gegooid (a rato van 800000/dag) en daarmee is de kous af.
Met deze code kom ik al aardig in de buurt van de output die ik hier reeds heb geplakt, op één detail na:
in de output zie je de timestamps steeds met 10 minuten verhogen. Met mijn query krijg je gewoon voor elke timestamp een resultaat en dat zijn er echt veel te veel. Dus nu ben ik op zoek naar een manier om in deze query een voorwaarde te plaatsen die aangeeft dat er slechts per 10 minuten een resultaat moet weergegeven worden.
Wat mijn code precies doet: de 3 variabelen die ik op het einde aanmerk selecteren en deze in een kolomvorm gooien via de JOIN instructie. Omdat er meerdere combinaties mogelijk zijn van StationName, GroupName en VariableName in de brontabel heb ik dus redelijk wat AND operators moeten plaatsen.
Nu wil ik dus nog een instructie plaatsen die er voor zorgt dat er alleen op (vorig)tijdstip + 10 minuten geselecteerd wordt binnen het interval van een maand. Hiervoor denk ik op dit moment aan volgende mogelijkheden:
- zoals ik met andere soortgelijke queries reeds gedaan heb: automatisch een tijdelijke tabel aanmaken met de gewenste timestamps in en deze joinen met de output van mijn query hierboven. Deze optie zou ik het liefst willen vermijden, het lijkt mij meer een bric-a-brac oplossing die mijn SQL onkunde aantoont.
- een andere transact sql oplossing: een eenvoudige loop programmeren die telkens een nieuwe query aanmaakt en uitvoert, maar dat kost volgens mij veel CPU van de server.
- werken met de DATEADD functie die mij hiervoor aangewezen lijkt. Alleen heb ik geen flauw idee waar ik deze juist zou moeten plaatsen. In de WHERE clausule levert hij maar één enkele record op (startdatum + 10 minuten logischerwijs). Ik heb ook reeds geprobeerd om de BETWEEN te combineren met deze functie, maar dat levert alleen maar veel error boodschappen op of slechts een enkelvoudige record als output: WHERE t1.LogDate BETWEEN(eerstedatum,DATEADD(mi,10,einddatum))
Nu is mijn vraag dus:
- kan ik überhaupt de DATEADD functie gebruiken om de timestamps per 10 minuten te verhogen ipv ze allemaal af te gaan? Zoja, waar moet ik die dan plaatsen?
- of ben ik gewoon in de verkeerde richting aan het zoeken?
Tot nog toe worden deze CSV bestanden gemaakt via een tool meegeleverd door de fabrikant v/d hardware die wij hier gebruiken. Helaas moet men wel manueel deze bestanden maken en hier gaan heel veel werkuren aan verloren, dus ik mag de zaak automatiseren.LogDate, AM25L\3Sec\ddd_10av, AM25L\3Sec\ff_10av, AM25L\3Sec\ff_10x
1/06/2013, 322, 9.5, 13.8
1/06/2013 00:10:00, 318, 9.9, 14.4
1/06/2013 00:20:00, 316, 9.7, 15.2
1/06/2013 00:30:00, 318, 9.9, 15.7
1/06/2013 00:40:00, 313, 9.7, 15
1/06/2013 00:50:00, 313, 9.3, 13.8
1/06/2013 01:00:00, 318, 8.2, 13
1/06/2013 01:10:00, 318, 8, 13
...
De structuur van de basistabel is zo dat er gewoon geen structuur, sortering of normalisering aanwezig is.
De meetgegevens worden gewoon op een hoop gegooid (a rato van 800000/dag) en daarmee is de kous af.
Met deze code kom ik al aardig in de buurt van de output die ik hier reeds heb geplakt, op één detail na:
in de output zie je de timestamps steeds met 10 minuten verhogen. Met mijn query krijg je gewoon voor elke timestamp een resultaat en dat zijn er echt veel te veel. Dus nu ben ik op zoek naar een manier om in deze query een voorwaarde te plaatsen die aangeeft dat er slechts per 10 minuten een resultaat moet weergegeven worden.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| SELECT t1.LogDate, t1.LogValue AS 'AM25L\3sec\ddd_10av', t2.LogValue AS 'AM25L\3sec\ff_10av', t3.LogValue AS 'AM25L\3sec\ff_10x' FROM [Log] t1 INNER JOIN [Log] t2 ON t1.LogDate = t2.LogDate INNER JOIN [Log] t3 ON t1.LogDate = t3.LogDate WHERE (t1.LogDate BETWEEN 'Jun 1 2013 00:00AM' AND 'Jun 30 2013 00:00AM') AND (t1.StationName = 'AM25L') AND (t2.StationName = 'AM25L') AND (t3.StationName = 'AM25L') AND (t1.GroupName = '3sec') AND (t2.GroupName = '3sec') AND (t3.GroupName = '3sec') AND (t1.VariableName = 'ddd_10av') AND (t2.VariableName = 'ff_10av') AND (t3.VariableName = 'ff_10x') ORDER BY t1.LogDate |
Wat mijn code precies doet: de 3 variabelen die ik op het einde aanmerk selecteren en deze in een kolomvorm gooien via de JOIN instructie. Omdat er meerdere combinaties mogelijk zijn van StationName, GroupName en VariableName in de brontabel heb ik dus redelijk wat AND operators moeten plaatsen.
Nu wil ik dus nog een instructie plaatsen die er voor zorgt dat er alleen op (vorig)tijdstip + 10 minuten geselecteerd wordt binnen het interval van een maand. Hiervoor denk ik op dit moment aan volgende mogelijkheden:
- zoals ik met andere soortgelijke queries reeds gedaan heb: automatisch een tijdelijke tabel aanmaken met de gewenste timestamps in en deze joinen met de output van mijn query hierboven. Deze optie zou ik het liefst willen vermijden, het lijkt mij meer een bric-a-brac oplossing die mijn SQL onkunde aantoont.
- een andere transact sql oplossing: een eenvoudige loop programmeren die telkens een nieuwe query aanmaakt en uitvoert, maar dat kost volgens mij veel CPU van de server.
- werken met de DATEADD functie die mij hiervoor aangewezen lijkt. Alleen heb ik geen flauw idee waar ik deze juist zou moeten plaatsen. In de WHERE clausule levert hij maar één enkele record op (startdatum + 10 minuten logischerwijs). Ik heb ook reeds geprobeerd om de BETWEEN te combineren met deze functie, maar dat levert alleen maar veel error boodschappen op of slechts een enkelvoudige record als output: WHERE t1.LogDate BETWEEN(eerstedatum,DATEADD(mi,10,einddatum))
Nu is mijn vraag dus:
- kan ik überhaupt de DATEADD functie gebruiken om de timestamps per 10 minuten te verhogen ipv ze allemaal af te gaan? Zoja, waar moet ik die dan plaatsen?
- of ben ik gewoon in de verkeerde richting aan het zoeken?
Clowns to the left of me, Jokers to the right