webForumDet fria alternativet

Period som int men dra bort en månad

Databaser & SQL

9 svar · 606 visningar · startad av Addeladde

Medlem sedan jan. 20013 406 inlägg
Frågan#1

Hej

Jag har en stored procedure som får en parameter @per int
Det består av årtal och månad. Tex. 200802

Nu vill jag i min sp använda mig av denna parameter men också föregående månad.

I de allra flesta fallen kan jag bara köra @per - 1 men det blir tyvärr fel vid årsskiftet 200801 -1 blir ju 200800 och inte 200712. Kan jag lösa detta på något enkelt sätt utan att skicka in ytterligare en parameter till funktionen?

Medlem sedan juni 20034 013 inlägg
#2

Enklaste sättet borde väl vara att tala om att det är ett datum och inte bara ett heltal vilket som helst?

Medlem sedan jan. 20013 406 inlägg
#3

Det går inte att ändra databasen uppbyggnad. Visst kan jag skicka in ett datum men det måste då konverteras till en int.

Medlem sedan juni 20034 013 inlägg
#4

Om du inte kan ändra databasens uppbyggnad så finns det inget enkelt sätt. Då måste du själv programmera in undantag som gör att den "räknar" rätt. Tyvärr har den som designat databasen gjort fel. Hade det varit en datumkolumn så hade den räknat rätt. Det är det datumkolumner är till för.

Medlem sedan juni 20034 013 inlägg
#5

Det du får göra är ju typ att efteråt:

if ((de två sista siffrorna) == "00")
{
(de två sista siffrorna) = "12";
(de fyra första siffrorna) = (de fyra första siffrorna) - 1;
}

Medlem sedan jan. 20013 406 inlägg
#6

Nu kör jag:

DECLARE @faktperPrev int
SET @faktperPrev = @faktper-1
IF SUBSTRING(CAST(@faktperPrev AS CHAR(6)),5,2) = '00' BEGIN
	SET @faktperPrev = (CAST(SUBSTRING(CAST(@faktper AS CHAR(6)),0,5) AS INT)-1)*100+12
END

Vilket ger rätt resultat men känns omständligt.

Medlem sedan juni 20008 205 inlägg
#7

Är inte helt hundra på hur man skriver det i SQL, men du kan ju göra om årtalet till månader-sedan-januari-0000, använda vanlig aritmetik på det och vända på processen för att få ut ett tal som liknar det du fick in.

Om vi antar att du har ett tal per = 200801, så kan du göra om det till ett heltal som motsvarar månader med följande formel:
months = (per / 100) * 12 + (per % 100)

Lägg till/ta bort månader efter ditt hjärtas lustan.

När man sen ska göra om det till ett år igen, blir det lite grisigare, men om vi tar det i steg:
yearpart = (month - 1) / 12
Sen tar vi fram månadsdelen med:
monthpart = ((month - 1) % 12) + 1
Sen är årtalet bara (yearpart * 100) + monthpart. Lite freestylat:

DECLARE @months int
DECLARE @yp int
DECLARE @mp int
DECLARE @faktPerPrev int
SET @months = (FLOOR(per / 100) * 12 + (per % 100)) - 1
SET @yp = (@months - 1) / 12
SET @mp = ((@months - 1) MOD 12) + 1
SET @faktperPrev = (@yp * 100) + @mp
END

Har ingen aning om ifall det är så det ska se ut, men i teorin är det rätt :)

Medlem sedan jan. 20013 406 inlägg
#8

Smart lösning och datorn räknar förmodligen betydligt snabbare eftersom man inte går över till stängar någonstans. Men skillnaden är förmodligen så marginell att mängden kod som din lösning genererar gör det onödigt att använda den?

Medlem sedan juni 20008 205 inlägg
#9

Addeladde skrev:

Men skillnaden är förmodligen så marginell att mängden kod som din lösning genererar gör det onödigt att använda den?

Om du bryr dig kan du ju testa :) men å andra sidan finns det ingen anledning att inte använda den (om det inte är ultrajobbigt att uppdatera dina befintliga SPar). Även om det inte gör nån skillnad nu, kan det teoretiskt tänkas göra skillnad när din applikation får en ny arbetsuppgift som anropar den här funktionen skitofta.

Medlem sedan jan. 20013 406 inlägg
#10

Japp

261 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
126 ms — deklarationer (db)
0 ms — hämta statistik (cache)
132 ms — hämta tråd, inlägg och bilagor (db)
127 ms — ändringar (db)