Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: SQL tauluun tiedon päivittäminen samasta taulusta

Sivun loppuun

FatalSunrise [31.03.2014 17:34:30]

#

Tällainen ongelma olisi, mutta menee hieman yli oman osaamisen, josko täällä joku osaisi jelppiä.

Taulusta VarastoPvk pitää päivittää kentät joissa on Keskihinta 0, keskihinta pitäisi hakea saman taulun rivistä, jossa on sama NimikeID, kuin keskihinta 0 riveissä, mutta sellainen rivi, jossa tapahtuma-kentän arvo on 2 (keskihinta 0 riveissä tapahtumakentän arvo on aina 1) ja koska rivejä saattaa olla monta, niin keskihinta tulisi hakea rivistä, jossa on lähin Päivämäärä (Paivays niminen kenttä) tuon keskihinta 0 rivin kanssa

Metabolix [31.03.2014 18:29:09]

#

UPDATE VarastoPvk v0
LEFT JOIN VarastoPvk v_prev ON v_prev.NimikeID = v0.NimikeID AND v_prev.Paivays < v0.Paivays AND v_prev.Keskihinta != 0
LEFT JOIN VarastoPvk v_prev_null ON v_prev_null.NimikeID = v0.NimikeID AND v_prev_null.Paivays > v_prev.Paivays AND v_prev_null.Paivays < v0.Paivays AND v_prev_null.Keskihinta != 0
LEFT JOIN VarastoPvk v_next ON v_next.NimikeID = v0.NimikeID AND v_next.Paivays > v0.Paivays AND v_next.Keskihinta != 0
LEFT JOIN VarastoPvk v_next_null ON v_next_null.NimikeID = v0.NimikeID AND v_next_null.Paivays < v_next.Paivays AND v_next_null.Paivays > v0.Paivays AND v_next_null.Keskihinta != 0
SET v0.Keskihinta = IF(v_next.NimikeID IS NULL OR TIMESTAMPDIFF(SECOND, v_prev.Paivays, v0.Paivays) <= TIMESTAMPDIFF(SECOND, v0.Paivays, v_next.Paivays), IF(v_prev.NimikeID IS NULL, 0, v_prev.Keskihinta), v_next.Keskihinta)
WHERE v0.Keskihinta = 0 AND v_prev_null.NimikeID IS NULL AND v_next_null.NimikeID IS NULL

Hyi. :D Käytä omalla vastuulla eli ota ensin varmuuskopio kannastasi, jos kanta on sinulle arvokas. Ehkä hyvä idea on luoda tauluun ensin uusi sarake apuhinta, johon teet tuon päivitysoperaation, ennen kuin hävität tiedon, mitkä hinnat olivat nollia.

Huomaathan, että kysely hakee hintoja sekä myöhemmistä että aiemmista riveistä. Jos haluat huomioida vain aiemmat rivit, poista kaikki next-tauluhin liittyvät osat.

FatalSunrise [31.03.2014 18:55:28]

#

Kiitos kovasti jelpistä. En sitten tajunnut sanoa, että kyseessä on MSSQL :( En siis saanut tuota toimimaan, kun ensimmäinenkään rivi ei Microsoft SQL Management studiolle kelvannut, vaikka muutinkin sen muotoon:

UPDATE [Yritys1].[dbo].[VarastoPvk] v0

ja tarkoitus olikin, että myöhemmät sekä aiemmat kelpaavat.

Teuro [31.03.2014 19:19:58]

#

Ajoithan siis koko kyselyn ja muutithan koko kyselyn käyttämäsi kannan hyväksymään muotoon? Tuossa ei siis ole seitsemää kyselyä, vaan yksi kysely, joka on pätkitty selvyyden vuoksi seitsemälle riville.

FatalSunrise [31.03.2014 19:36:14]

#

yritin kyllä ajaa koko kyselyn, mutta ongelmaksi muodostui juuri tuo Microsoft SQL:n muotoon muuttaminen. Update odottaa SET käskyä ennen LEFT JOINIa ja, mikäli nostan sen ylös, niin v_next.NimikeID ei tunnistu.

feenix [31.03.2014 20:45:36]

#

MS SQL:llä pitäisi mennä näin:

update v0 set ...
from VarastoPvk v0
left join ...
where ...

FatalSunrise [31.03.2014 20:54:51]

#

Kiitos avusta, noin itsekin ajattelin, mutta nyt ongelmana on tuo IF, pitäisi ilmeisesti olla CASE tai IIF. Vielä selvennykseksi, että kyseessä on SQL Sever 2012. Tämän serveri hyväksyisi muutoin, mutta nuo IFit pitäisi muuttaa:

UPDATE [Yritys1].[dbo].[VarastoPvk]
SET [Yritys1].[dbo].[VarastoPvk].Keskihinta = IF(v_next.NimikeID IS NULL OR DATEDIFF(SECOND, v_prev.Paivays, v0.Paivays) THEN DATEDIFF(SECOND, v0.Paivays, v_next.Paivays), IF(v_prev.NimikeID IS NULL, 0, v_prev.Keskihinta), v_next.Keskihinta)
FROM [Yritys1].[dbo].[VarastoPvk] as v0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_prev ON v_prev.NimikeID = v0.NimikeID AND v_prev.Paivays < v0.Paivays AND v_prev.Keskihinta != 0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_prev_null ON v_prev_null.NimikeID = v0.NimikeID AND v_prev_null.Paivays > v_prev.Paivays AND v_prev_null.Paivays < v0.Paivays AND v_prev_null.Keskihinta != 0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_next ON v_next.NimikeID = v0.NimikeID AND v_next.Paivays > v0.Paivays AND v_next.Keskihinta != 0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_next_null ON v_next_null.NimikeID = v0.NimikeID AND v_next_null.Paivays < v_next.Paivays AND v_next_null.Paivays > v0.Paivays AND v_next_null.Keskihinta != 0
WHERE v0.Keskihinta = 0 AND v_prev_null.NimikeID IS NULL AND v_next_null.NimikeID IS NULL

feenix [01.04.2014 06:40:10]

#

Totta, en katsonutkaan noin tarkasti. Moiset iffit ovat minusta hyihyi, mieluummin käyttää ihan standardi-SQL:n case-when-juttuja, mutta kantaspesifisiin tottuneet varmaan noita käyttelevät. Itse en tuosta variantista osaa sanoa miten menisi, koska tuo THEN tuolla keskellä IFfiä hämää. Muutehan tuo menisi ihan yksinkertaisesti IF(a, b, c) -> case when a then b else c end.

FatalSunrise [01.04.2014 11:49:01]

#

Nyt en todellakaan osaa sanoa, että mistä tuonne koodiin oli tuo THEN tullut, mutta näin sen koodin olisi pitänyt olla:

UPDATE [Yritys1].[dbo].[VarastoPvk]
SET [Yritys1].[dbo].[VarastoPvk].Keskihinta = IF(v_next.NimikeID IS NULL OR DATEDIFF(SECOND, v_prev.Paivays, v0.Paivays) <= DATEDIFF(SECOND, v0.Paivays, v_next.Paivays), IF(v_prev.NimikeID IS NULL, 0, v_prev.Keskihinta), v_next.Keskihinta)
FROM [Yritys1].[dbo].[VarastoPvk] as v0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_prev ON v_prev.NimikeID = v0.NimikeID AND v_prev.Paivays < v0.Paivays AND v_prev.Keskihinta != 0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_prev_null ON v_prev_null.NimikeID = v0.NimikeID AND v_prev_null.Paivays > v_prev.Paivays AND v_prev_null.Paivays < v0.Paivays AND v_prev_null.Keskihinta != 0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_next ON v_next.NimikeID = v0.NimikeID AND v_next.Paivays > v0.Paivays AND v_next.Keskihinta != 0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_next_null ON v_next_null.NimikeID = v0.NimikeID AND v_next_null.Paivays < v_next.Paivays AND v_next_null.Paivays > v0.Paivays AND v_next_null.Keskihinta != 0
WHERE v0.Keskihinta = 0 AND v_prev_null.NimikeID IS NULL AND v_next_null.NimikeID IS NULL

Lisäys:

Nyt koodi on käsittääkseni muokattu tarvitsemaani muotoon. Illemmalla pääsee sitten testailemaan tuon toimintaa.

UPDATE v0
SET v0.Keskihinta = CASE
WHEN v_next.NimikeID IS NULL OR DATEDIFF(SECOND, v_prev.Paivays, v0.Paivays) <= DATEDIFF(SECOND, v0.Paivays, v_next.Paivays)
THEN CASE
	WHEN v_prev.NimikeID IS NULL
	THEN 0
	ELSE v_prev.Keskihinta
	END
ELSE v_next.Keskihinta
END
FROM [Yritys1].[dbo].[VarastoPvk] as v0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_prev ON v_prev.NimikeID = v0.NimikeID AND v_prev.Paivays < v0.Paivays AND v_prev.Keskihinta != 0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_prev_null ON v_prev_null.NimikeID = v0.NimikeID AND v_prev_null.Paivays > v_prev.Paivays AND v_prev_null.Paivays < v0.Paivays AND v_prev_null.Keskihinta != 0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_next ON v_next.NimikeID = v0.NimikeID AND v_next.Paivays > v0.Paivays AND v_next.Keskihinta != 0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_next_null ON v_next_null.NimikeID = v0.NimikeID AND v_next_null.Paivays < v_next.Paivays AND v_next_null.Paivays > v0.Paivays AND v_next_null.Keskihinta != 0
WHERE v0.Keskihinta = 0 AND v_prev_null.NimikeID IS NULL AND v_next_null.NimikeID IS NULL

FatalSunrise [02.04.2014 11:49:51]

#

Suuret kiitokset vaan kaikille avusta! Nyt homma toimii. Mitään ei olisi tullut ilman teitä Metabolix ja feenix. Alla vielä koodi lopullisessa muodossaan:

UPDATE v0
SET v0.Keskihinta = CASE
WHEN v_next.NimikeID IS NULL
THEN CASE
	WHEN v_prev.NimikeID IS NULL
	THEN 0
	ELSE v_prev.Keskihinta
	END
ELSE v_next.Keskihinta
END
FROM [Yritys1].[dbo].[VarastoPvk] as v0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_prev ON v_prev.NimikeID = v0.NimikeID AND v_prev.Paivays < v0.Paivays AND v_prev.Keskihinta != 0 AND v_prev.Tapahtuma = 2
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_prev_null ON v_prev_null.NimikeID = v0.NimikeID AND v_prev_null.Paivays > v_prev.Paivays AND v_prev_null.Paivays < v0.Paivays AND v_prev_null.Keskihinta != 0
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_next ON v_next.NimikeID = v0.NimikeID AND v_next.Paivays >= v0.Paivays AND v_next.Keskihinta != 0 AND v_next.Tapahtuma = 2
LEFT JOIN [Yritys1].[dbo].[VarastoPvk] v_next_null ON v_next_null.NimikeID = v0.NimikeID AND v_next_null.Paivays < v_next.Paivays AND v_next_null.Paivays > v0.Paivays AND v_next_null.Keskihinta != 0
WHERE v0.Keskihinta = 0 AND v_prev_null.NimikeID IS NULL AND v_next_null.NimikeID IS NULL AND v0.Tapahtuma = 1

Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta