Avatar billede osborne Nybegynder
10. marts 2007 - 19:06 Der er 9 kommentarer og
1 løsning

En avanceret UPDATE ?

Vi har en tabel (TREE) i vores database som beskriver en træstruktur. ID er unik identifikation af hver mappe i træstrukturen, Father_ID angiver hvilken mappe hver mappe har som forældre i strukturen. De mapper som ligger på øverste niveau har Father_ID=0. Hver mappe har også et navn.

Tabel: TREE

ID: 1,  Father_ID: 0, navn: '01. forår'
ID: 2,  Father_ID: 2, navn: '01.01 guld'
ID: 3,  Father_ID: 2, navn: '01.02 sølv'
ID: 4,  Father_ID: 2, navn: '01.03 bronce'

ID: 5,  Father_ID: 0, navn: '02. sommer'
ID: 6,  Father_ID: 5, navn: '01.01 guld'
ID: 7,  Father_ID: 5, navn: '01.02 sølv'
ID: 8,  Father_ID: 5, navn: '01.03 bronce'

ID: 9,  Father_ID: 0, navn: '02. sommer'
ID: 10, Father_ID: 9, navn: '01.01 guld'
ID: 11, Father_ID: 9, navn: '01.02 sølv'
ID: 12, Father_ID: 9, navn: '01.03 bronce'

osv.

Opgaven er nu at skrive en SQL sætning (eller flere) som sørger for at mapperne i andet niveau alle får udskiftet første tre tegn af deres navn så det svarer til første del af navnet i den overliggende mappe (dvs. fra deres father). I eksemplet neden for skal f.eks. ID 6,7 og 8 alle have uskiftet 01. med 02 i deres navn. Der er kun to nivauer i træstrukturen, dvs. yderste niveau (med Father_ID=0) og så de samme undermapper til hver.  Alle disse undermapper skal altså omdøbes så starten af deres navn afspejler tallet angivet i overmappen.


Vores løsning er indtil videre at skrive en bunke SQL sætninger der hver for sig klarer indholdet i en overordnet mappe:

UPDATE tree SET navn = '02.' + substring(navn,4,100) WHERE Father_ID = 5
UPDATE tree SET navn = '03.' + substring(navn,4,100) WHERE Father_ID = 9
osv.   

Jeg drømmer dog om at finde en måde hvor vi kunne skrive en super SQL statement som kunne klare det hele i et hug .. måske ved inde i UPDATEN sørge for at der er en select som udtrækker det nødvendige fra father, eller noget .. men er gået lidt kold på dette.

Er der nogen der har en ide til om og hvordan dette kunne gøres?
På forhånd tak
Avatar billede osborne Nybegynder
10. marts 2007 - 19:08 #1
Rettelse: rækken ID:9 skulle have haft navn: '03. efterår'
Avatar billede dr_chaos Nybegynder
10. marts 2007 - 20:51 #2
Måske noget i denne stil:
declare @minID int, @maxID int
SELECT @minID= min(id), @maxID=max(id) FROM TREE WHERE Father_ID=0
WHILE @minID<=@maxID
BEGIN

UPDATE t SET t.Navn=substring(tParent.navn,0,2)+''+substring(T.navn,2,100) FROM Tree T JOIN Tree tParent ON tParent.ID = T.Father_ID
WHERE T.Father_ID=@minID

SELECT @minID= min(id)FROM TREE WHERE Father_ID=0 AND id>@minID
END
Avatar billede dr_chaos Nybegynder
10. marts 2007 - 20:52 #3
måske endda:
UPDATE t SET t.Navn=substring(tParent.navn,0,3)+''+substring(T.navn,2,100) FROM Tree T JOIN Tree tParent ON tParent.ID = T.Father_ID
WHERE T.Father_ID=0
Avatar billede dr_chaos Nybegynder
10. marts 2007 - 20:52 #4
substring(tParent.navn,0,2) skal være substring(tParent.navn,0,3) i første eksempel.
Avatar billede osborne Nybegynder
11. marts 2007 - 00:41 #5
Takker, det må jeg lige studere .. Vi sidder med et SQL interface direkte i applikationen som kun tillader at man udfører en SQL sætning af gangen interaktivt, jeg er ikke sikker på at den håndterer declare af lokale variable - men det må jeg undersøge.

Der hvor du skriver måske endda .. er det skud på en SQL sætning der klarer det hele? Jeg må lige se nærmere på den.

Vender tilbage
Avatar billede osborne Nybegynder
11. marts 2007 - 02:22 #6
Jeg har nu været logget på vores database, fundet de rigtige tabel og kononnenavn (så de ikke længere blot er fra hukommelsen) og testet dit andet forslag. Underligt nok uden at den ændrer navnene...

Her først lige dataeksemplet igen med de korrekte kollonnenavne:

Tabel: cycl_fold

cf_item_id: 1,  cf_father_ID: 0, navn: '01. forår'
cf_item_id: 2,  cf_father_id: 2, cf_item_name: '01.01 guld'
cf_item_id: 3,  cf_father_id: 2, cf_item_name '01.02 sølv'
cf_item_id: 4,  cf_father_id: 2, cf_item_name: '01.03 bronce'

cf_item_id: 5,  cf_father_id: 0, cf_item_name: '02. sommer'
cf_item_id: 6,  cf_father_id: 5, cf_item_name: '01.01 guld'
cf_item_id: 7,  cf_father_id: 5, cf_item_name: '01.02 sølv'
cf_item_id: 8,  cf_father_id: 5, cf_item_name: '01.03 bronce'

cf_item_id: 9,  cf_father_id: 0, cf_item_name: '03. efterår'
cf_item_id: 10, cf_father_id: 9, cf_item_name: '01.01 guld'
cf_item_id: 11, cf_father_id: 9, cf_item_name: '01.02 sølv'
cf_item_id: 12, cf_father_id: 9, cf_item_name: '01.03 bronce'

osv.

SQL sætningen:

UPDATE t set t.cf_item_name=substring(tParent.cf_item_name,1,3)+substring(t.cf_item_name,4,100)
FROM cycl_fold t join cycl_fold tParent ON tParent.cf_item_id = t.cf_father_id
where t.cf_father_id=0

Gav som sagt ikke noget resultet (dvs. helt tomt) !?

Hvis jeg lige tester med en select så giver følgende et helt tomt resultat:

select * from cycl_fold t join cycl_fold tParent ON tParent.cf_item_id=t.cf_father_id where t.cf_father_id=0

Kan det måske være noget med at det skal være en inner (eller outer) join eller sådan noget istedet (og hvordan er det nu man skriver det)?

Tak indtil videre, jeg er sikker på at vi er på rette spor :-)
Avatar billede dr_chaos Nybegynder
11. marts 2007 - 08:58 #7
Det var noget jeg lavede ud fra hovedet så jeg kan godt forstå at jeg ikke rammer helt rigtigt :)

Det er mig som har vendt den lidt forkert, prøv lige med:
select * from cycl_fold t join cycl_fold tParent ON tParent.cf_item_id=t.cf_father_id where t.cf_father_id>0
Avatar billede dr_chaos Nybegynder
11. marts 2007 - 08:59 #8
Hvis den virker så burde det rigtige være:
UPDATE t set t.cf_item_name=substring(tParent.cf_item_name,1,3)+substring(t.cf_item_name,4,100)
FROM cycl_fold t join cycl_fold tParent ON tParent.cf_item_id = t.cf_father_id
where t.cf_father_id>0
Avatar billede osborne Nybegynder
11. marts 2007 - 15:17 #9
Åh ja, det burde jeg have set, faktisk havde jeg i mine eksprimenter med selecten på et tidspunkt tænkt på >0 og prøvet det, men af en eller anden grund forventede jeg ikke at få de rækker, men det var så det rigigte alligevel ... den virker! Det er dog utroligt at du sådan lige kan lide det af ud fra hovedet :-) Tusind tak for hjælpen.

Læg venligst et 'svar' så jeg kan give dig nogle point.
Avatar billede dr_chaos Nybegynder
11. marts 2007 - 15:27 #10
Man kan kun sige at erfaring ikke er en dårlig ting :)
svar :)
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