Vinnaren i pepparkakshustävlingen!
2013-04-28, 19:51
  #1
Medlem
Tjena. Har suttit och pillat lite utan att få löst ett litet problem.

Min tabell heter nuts och har 5 columner.

code (kod betäckning för städerna)
name (namn på städer)
country_order (int 1-100) unikt för varje land, exempel sverige har order 26 tillsammans med alla dess städer
level (int 0-2) 0 land, 1 län, 2 städer
version (enum, 2003,2008)
---------------

Om ni har jobbat med upphandlingar tidigare så vet ni vad nuts-koder är. Annars kan ja försöker förklara lite snabbt.

Min tabell består av länder, dess städer och län. Det finns 2 olika versioner på koderna som presenterades 2003 samt 2008 enligt europeiska unionen.

Jag har lagt in alla koder från 2003 samt 2008 i en och samma tabell.
Vissa koder har inte förändrats sedan 2003 och är desamma även 2008. Dock så kan det finnas vissa koder i 2003 som inte finns med i 2008 och tvärtom. Städer kan ha lagts till eller tagits bort mellan dem två versionerna också.

Vad jag vill göra är simpelt.

Jag vill selecta alla nuts koder från både 2008 samt 2003. Om staden heter samma sak i 2003 samt 2008 men har olika koder så vill jag presentera det i 2 olika kolumner, finns staden i ena tabellen men inte i den andra så ska den fortfarande tas med, fast ja måste veta vilken version det är.

Så här såg min sql fråga ut som inte fungerar för alla länder.

Kod:
SELECT nuts_2003.name AS name_2003,nuts_2003.country_order AS country_order_2003,nuts_2003.level AS level_2003,nuts_2003.code AS code_2003,nuts_2008.name AS name_2008,nuts_2008.country_order AS country_order_2008,nuts_2008.level AS level_2008,nuts_2008.code AS code_2008 FROM nuts AS nuts_2008
LEFT JOIN nuts 
AS nuts_2003 ON nuts_2008.name nuts_2003.name
WHERE nuts_2008
.country_order '26' AND nuts_2008.name NOT LIKE 'Extra%' AND nuts_2008.version '2008' AND nuts_2003.version '2003' 

Här har jag bara försökt matcha namnen. Jag vet helt enkelt inte hur jag ska göra för att få med allting då det egentligen inte finns någon tydligt relationer mellan koderna.

Som exempel kan västra götalands län ha kod SE01 i 2003 versionen medan den har SE101 i 2008 versionen.

Jobbigare blir det om en stad finns med i 2003 versionen men inte 2008. Hur går jag tillväga?
__________________
Senast redigerad av newone 2013-04-28 kl. 19:57.
Citera
2013-04-28, 22:01
  #2
Medlem
Kan kanske förklara lite mer.
Utdata bör se ut så här:

code_2008 - code_2003 - name_2008 - name_2003

BF1 - BF2 - Västra götaland - Västra götaland
BE2 - (tomt) - Skåne - (tomt)
(tomt) - XF1 - (tomt) - kista

då är ni med på vad jag pratar om.

Om namnet finns med i både 2003 och 2008 versionen, då vill jag ha ut både 2003 samt 2008 code.
finns namnet bara i 2003, så ska code för 2003 tas med, finns namnet bara i 2008, så ska bara 2008 code tas med.

med andra ord. Ta alla namn från tabellen, om namnet finns med i både 2003 och 2008, ta med båda koderna i samma rad.
Citera
2013-04-28, 22:19
  #3
Medlem
John-Pauls avatar
Det kanske underlättar och blir tydligt om du delar upp uppgiften i flera sql-satser (enligt devisen keep it simple)

Nått i stil med:
1. Om staden heter samma sak i 2003 samt 2008 men har olika koder så vill jag presentera det i 2 olika kolumner
2. finns staden i 2003 men inte i 2008
3. finns staden i 2008 men inte i 2003
4. plocka ihop svaren i ett trevligt resulatset
__________________
Senast redigerad av John-Paul 2013-04-28 kl. 22:37.
Citera
2013-04-28, 22:30
  #4
Medlem
Google ger som första träff:
http://stackoverflow.com/questions/3...and-outer-join

Du kan använda "outer join" , och då kommer värden som inte finnas att vara NULL.

Tycker annars du inte borde lagra allt i 1 tabell.
1 tabell för "landområden" ( = län, tex Västra Götaland )
1 tabell för Städer ( Tex Göteborg , Stockholm et.c.)

Sedan lagrar du koderna 1 en annan tabell
Tabellerna ovan är typ:
City: id Int, Name String

Sedan ha 1 tabell med koder för varje "stad"
Kod:
Create table CityCodes (
 
Country_id int NOT NULL,
 
City_id int NOT NULL,
 
code varchar(64),
 
Code_type int NOT NULL, -- "type 0 för SEQ2003 och 1 för 2008"
 
FOREIGN KEY (City_idREFERENCES City(Id)
 
FOREIGN KEY (Country_idREFERENCES Country(Id)
); 
All själva datan som du behöver finns i CityCodes, men för att få ut Namn på Städer respektive Länder får du Joina med de tabellerna.
OBS ej testat men borde bli något mera i stil med följande:
Kod:
select City.namec1.codec2.code from City 
 outer join CityCodes c2 on c1
.city_Id=City.Id 
 outer join City on c1
.city_Id=City.Id
 where c1
.code_type=and c2.code_type=0
OBS ej testat koden ovan.
Citera
2013-04-28, 22:37
  #5
Medlem
Fixade 1 uppenbart fel i min sista sql
Kod:
select City.namec1.codec2.code from City  
 outer join CityCodes c1 on c1
.city_Id=City.Id  
 outer join CityCodes c2 on c2
.city_Id=City.Id 
 where c1
.code_type=and c2.code_type=0

Sedan är ju code_type dåligt valt namn tycker jag här(av mig), borde vara code_id som är int not null och foreign key till en tabell..( Med 2 rader "SEQ 2003" och "SEO_2008" )

Håll det gärna på engelska.
Välj korrekt namn på alla saker, lägg ned åtminstone ett par minuter på varje NAMN du sätter.
( Kolumner, tabell namn etc )
Citera
2013-04-28, 23:21
  #6
Medlem
nu är det så att ja inte riktigt kan dela upp allting i olika tabeller, nuts koder är redan ett helvete att arbeta med läs lite om det på nätet så förstår du.

Sedan så finns det ingen outer join implementerat i mysql så jag får jobba med union och ska ja vara helt ärligt så blir jag heeelt efterbliven när jag sitter och skriver ihop left join, right join + union ihop. kanske är lite försend för mig.

Men du har rätt, en outer join är det som krävs, för att ta med resultaten från tabellen 2 gånger, en för 2003 versionen och en för 2008. Matchningen som finns i 2008 ska heta code_2008 samt name_2008, och från matchingen från 2003 ska heta code_2003 samt name_2003. Finns det ingen match så kan den kolumnen som inte har någonting med versionen att göra vara tom.
Citera
2013-04-28, 23:35
  #7
Medlem
Gjorde livet lite enklare och la in alla nuts koder för 2003 i egen tabell, respektive 2008 i en annan.

Kod:
SELECT nuts_2003.code as code_2003,nuts_2008.code as code_2008,nuts_2003.name as name_2003,nuts_2008.name as name_2008 FROM nuts_2003
RIGHT JOIN nuts_2008 ON nuts_2003
.name nuts_2008.name
WHERE nuts_2008
.country_order '26' AND nuts_2008.name NOT LIKE 'extra%'
UNION
SELECT nuts_2003
.code as code_2003,nuts_2008.code as code_2008,nuts_2003.name as name_2003,nuts_2008.name as name_2008 FROM nuts_2008
LEFT JOIN nuts_2003 ON nuts_2003
.name nuts_2008.name
WHERE nuts_2003
.country_order '26' AND nuts_2003.name NOT LIKE 'extra%' 

Sådär löste det jag det. Tack för alla svaren
Citera

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback