Skrivet av atman:
Jag använder mig av MSSQL 2008.
Har inte något index på saldo, jag läste lite om index etc när jag skapade tabellen och fick rådet att inte använda för många. Så jag har bara ett enda index i tabellen som är kopplat till ett id bara.
Funderade på det också, går det ta fram endast de artiklarna som är äldre än ett år.
Som jag gör nu så sorterar jag ut dem i tjänsten (skriven i c#) med ett timespan.
Det är ju när jag fått fram en array med artiklar som är äldre än 1 år som det tar tid.
Måste ju köra en select * where artikel='array[i]' för varje artikel för att få fram alla transaktioner per artikel.
Helt optimalt vore om jag i kunde genom SQL-frågor få fram alla artiklar(inkl transaktioner) på artiklar äldre än 365 dagar.
Så 30 sekunder är bra, det som tar tid är som den sista biten, ta fram alla transaktioner per artikel och insert/deletea.
Jag använder mig av en annan tabell för att lägga historiken i ja.
Det stämmer att man inte ska använda för många index, eftersom de kostar att underhålla dem, men det är en avvägning över hur mycket prestanda de ger.
Om dina tabeller sällan uppdateras så kan du använda index utan att tänka, men uppdateras dem ofta (insert/delete/update) så kan kostnaden bli för hög.
Har ingen tidigare erfarenhet av MSSQL, så detta blir otestat, men borde väl stämma någolunda:
SELECT artikel FROM produkt GROUP BY artikel HAVING max(saldo)=0 AND datediff(year,max(datum),getdate())>0
Detta borde alltså ge dig alla artiklar som är slut och som inte uppdaterats på över ett år. (Men ville du att alla artiklar, oavsätt om de var slut eller inte, skulle hittas baserat på datumet? Isf skippa max(saldo)=0 delen)
Bytte ut sum(saldo)=0 mot max(saldo)=0 eftersom max inte behöver gå igenom alla värden, såfort den hittar en 1:a så kan den sluta (sum måste fortsätta och beräkna summan eftersom den "kan" komma ett negativt tal, om du inte använder någon icke-negativ datatyp och SQL parsern är tillräckligt smart vid optimeringen).
Du kan sedan använda ovanstående query som subquery för att läsa ut alla transaktioner också:
SELECT * FROM produkt WHERE artikel in (SELECT artikel FROM produkt GROUP BY artikel HAVING max(saldo)=0 AND datediff(year,max(datum),getdate())>0) as t2
Och du kan sedan använda ovanstående för att skapa en INSERT för insättning i din backup-tabell, enligt:
INSERT INTO annan_tabell(artikel,datum,händelse,lagerhylla, saldo) (SELECT artikel,datum,händelse,lagerhylla,saldo FROM produkt WHERE artikel in (SELECT artikel FROM produkt GROUP BY artikel HAVING max(saldo)=0 AND datediff(year,max(datum),getdate())>0) as t2) as t3
Det som saknas då är att köra en avslutande DELETE i produkt-tabellen på artiklarna du kopierade till annan_tabell:
DELETE FROM produkt WHERE artikel in (SELECT artikel FROM produkt GROUP BY artikel HAVING max(saldo)=0 AND datediff(year,max(datum),getdate())>0) as t2
Har ingen MSSQL att testa emot, så har säkert missat paranteser och sånt, och koden är ju otestad så kör inte någon av INSERT/DELETE frågorna på data som är viktig.