Avatar billede Slettet bruger
27. august 2010 - 22:44 Der er 13 kommentarer og
1 løsning

Select med DATEPART(Month), men også med specifikt år

Hej.

Jeg forsøger at trække nogle poster ud fra en SQL Server database, ud fra to datoer/måneder.
Værdierne kan have fra 01-12 i henholdsvis den ene værdi (startDate) og (endDate), der begge vælges i en dropdown liste.

Min select ser ud som følger:

command.CommandText = "SELECT * FROM Orders";
            command.CommandText += " WHERE DATEPART(MONTH, OrderDate) BETWEEN '" + startDate + "' AND '" + endDate + "'";
            command.CommandText += " ORDER BY OrderId DESC";

Det virker umiddelbart så langt at jeg får 433 poster, men jeg ved at der skal være omkring 99.
Grunden er så nok at jeg henter alle poster fra fx. januar (01) til juni (06), men jeg skal kun bruge dem for et aktuelt år.

Hvordan laver man min selct så den også tager året med?
Avatar billede janus_007 Nybegynder
27. august 2010 - 23:45 #1
Hvis du har året og er ligeglad med performance så..

command.CommandText = "SELECT * FROM Orders";
            command.CommandText += " WHERE cast(DATEPART(YEAR, OrderDate) as varchar(4)) + cast(DATEPART(MONTH, OrderDate) as varchar(2)) BETWEEN '" + "2010" + startDate + "' AND '" + "2010" + endDate + "'";
            command.CommandText += " ORDER BY OrderId DESC";


Selv lige fylde 2010 + endDate med noget dynamisk :)
Avatar billede Slettet bruger
28. august 2010 - 10:06 #2
Hej Janus.
Tak for det. Grundlæggende er jeg egentlig ligeglad med performance - det er et script, der skal afvikles et par gange årligt, men jeg vil da gerne høre om versionen med den gode performance :-)
Hvorfor har denne version en mindre god performance? Er det fordi den trækker data to gange for henholdsvis måned og år?
Avatar billede janus_007 Nybegynder
28. august 2010 - 16:06 #3
Hej Thomas

Som tommelfingerregel skal man altid undgå at have funktioner på feltværdier, ved at have en datepart på OrderDate vel indexet ikke kunne udnyttes, derved vil query planen vælge full table scan og det tager længere tid jo flere rækker der er :)

I din query kan det være lidt kompliceret for vi vil jo gerne have hele måneder, men igen... og nu siger du den ikke skal køre så ofte... men ellers ville man designe efter det. Det kan hurtigt blive kompliceret :)
Avatar billede Slettet bruger
28. august 2010 - 16:14 #4
Ok. Tak for dit svar.
Du har været til mere end nok hjælp, har dog ikke prøvet din select endnu, men hvis du kender en anden metode, hvor der ikke bruges så mange ressourcer ville det da være fedt at få den også.

Men ellers lægger du bare et svar :-)
Avatar billede Slettet bruger
31. august 2010 - 15:27 #5
Hej Janus.

Når jeg smider din select ind i min kode, så returnerer den 0 poster?
Jeg er ret sikker på at der skal være omkring 100.

I min kildekode kan jeg se at begge dropdownlister har sat den rigtige værdi til selected - fx. startData er 01 og endDate er sat til 06 - som jo så skal være mit månedsinterval.

Har jeg overset noget?
Avatar billede Slettet bruger
31. august 2010 - 15:40 #6
Jeg har smidt select ind i query editor i SQL Server som:

SELECT OrderId, OrderDate, OrderPrice FROM [discountdomains_dk_db].[dbo].[Orders]
WHERE cast(DATEPART(YEAR, OrderDate) as varchar(4)) + cast(DATEPART(MONTH, OrderDate) as varchar(2)) BETWEEN '" + "2010" + 01 + "' AND '" + "2010" + 06 + "'
ORDER BY OrderId DESC

Men den returnerer også kun 0 poster.
Avatar billede janus_007 Nybegynder
31. august 2010 - 20:13 #7
Nåh for hulen...

Og du er sikker på der er 2010 datoer?

Jeg kan ikke lige se hvad der sker her:
BETWEEN '" + "2010" + 01 + "' AND '" + "2010" + 06 + "'

For test gør sådan her:
SELECT OrderId, OrderDate, OrderPrice FROM [discountdomains_dk_db].[dbo].[Orders]
WHERE cast(DATEPART(YEAR, OrderDate) as varchar(4)) + cast(DATEPART(MONTH, OrderDate) as varchar(2)) BETWEEN '201001' AND '201006'
ORDER BY OrderId DESC
Avatar billede Slettet bruger
01. september 2010 - 11:57 #8
Arh, jeg tror jeg ved hvorfor den returnerer 0 poster.
Hvis jeg fjerner de foranstillede nuller fra de værdier jeg sender med fra min ASPX-side så virker det umiddelbart.

Eller hvis man omskriver din select til:

SELECT OrderId, OrderDate, OrderPrice, cast(DATEPART(YEAR, OrderDate) as varchar(4)) + cast(DATEPART(MONTH, OrderDate) as varchar(2)) FROM [discountdomains_dk_db].[dbo].[Orders]
WHERE cast(DATEPART(YEAR, OrderDate) as varchar(4)) + cast(DATEPART(MONTH, OrderDate) as varchar(2)) BETWEEN '20101' AND '20106'
ORDER BY OrderId DESC

SQL Server opererer åbenbart ikke med foranstillede nuller, men i stedet med datoer som 2010 6 - i stedet for det jeg ville formode 2010 06.

Men jeg skal så lige have lavet nogle krydstjek på forskellige datointervaller så jeg er 100% sikker på at jeg får det ud jeg forventer hver gang - både med støøre intervaller, der spænder over flere år osv.

Tak for din hjælp! Smid et svar :-)
Avatar billede janus_007 Nybegynder
01. september 2010 - 13:47 #9
uakk.. sandt hehe...

Det kan du hurtigt klare med en right, sådan her:

right('0' + cast(DATEPART(MONTH,OrderDate) as varchar(2)), 2)

Altså:
SELECT OrderId, OrderDate, OrderPrice, cast(DATEPART(YEAR, OrderDate) as varchar(4)) + right('0' + cast(DATEPART(MONTH,OrderDate) as varchar(2)), 2) FROM [discountdomains_dk_db].[dbo].[Orders]
WHERE cast(DATEPART(YEAR, OrderDate) as varchar(4)) + right('0' + cast(DATEPART(MONTH,OrderDate) as varchar(2)), 2) BETWEEN '20101' AND '20106'
ORDER BY OrderId DESC
Avatar billede Slettet bruger
01. september 2010 - 14:01 #10
Ja ok. Men jeg har så som skrevet valgt at sende fra 1-12 ned i systemet fra min ASPX-side. Det ser ud til at virke. Men kan det på nogen måder give et problem? Jeg kan ikke lige overskue det nu, men vil som sagt krydstjekke med forskellige intervaller og årstal, men hvis du på forhånd siger at det vil skabe problemer i forhold til den løsning du selv kommer med, så vil jeg nok vælge din sidste løsning :-)
Avatar billede janus_007 Nybegynder
01. september 2010 - 22:01 #11
Den løsning med right er den jeg plejer at bruge. Men jeg kan nu heller ikke se hvorfor din skulle fejle :)
Avatar billede Slettet bruger
02. september 2010 - 22:09 #12
Hehe. Min løsning viser sig kun at returnere det rigtige antal så længe jeg ikke vælger måneder, der er større end et ciffer - altså fra Januar til September - eller 1-9.
Så snart jeg vælger én af de tre sidste måneder som slut i intervallet, så returneres der enten ingenting eller kun ganske få poster.

Har prøvet at implementere den du skrev til sidst med right, men så returneres der absolut ingen poster :-(
Avatar billede Slettet bruger
02. september 2010 - 22:18 #13
Har du egentlig nogen ide om hvorfor SQL Server kun returnerer poster for fx. Januar, hvis jeg vælger 20101 til 201012 ?

Det jeg skrev før med at det ikke virkede med de sidste 3 måneder var så åbenbart ikke helt sandt. Prøvede lige igen efter at have rettet noget tilbage og så viser den alle ordrer for 2009 hvis jeg vælger fra januar 2009 til december 2009.

Men problemet med at den returnerer poster for én måned hvis man vælger et interval, hvor der enten ikke er poster for de sidste måneder, eller slutdatoen ligger efter dags dato kan jeg så ikke lige forstå...
Ved så ikke lige hvilken af grundene der gør sig gældende, men gætter på at det er én af dem siden det ikke virker for 2010, men for 2009...
Avatar billede Slettet bruger
02. september 2010 - 22:23 #14
Ok, det er så åbenbart den sidste grund - altså den med at de sidste 3 måneder hvor der er to cifre ikke virker når der ingen ordrer er for disse måneder.
Når jeg vælger Januar 2010 til September 2010 viser den faktisk alle ordrerne, selvom den sidste ordre, der er i den lokale database er fra midten af august.
Men vælger jeg oktober i stedet, så listes kun ordrerne for januar måned?

Har ikke det store kendskab til SQL Server, men det virker ret mærkeligt på mig det her!
Hvis man ikke lave en between og få alle poster bare fordi slutdatoen enten er uden for 'scope' eller fordi der ikke findes nogle poster, så er det da ikke så pålideligt :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester