Permalänk
Medlem

SQL syntax senaste ägare

Hej

Jag försöker knåpa ihop en SQL syntax för att ta reda på senaste ägaren för ett fordon i en MSSQL databas men lyckas inte riktigt lista ut hur jag skall få det att fungera. Följande tabeller har jag i databasen

Struktur
Bussar = Innehåller ca 50 000 olika bussar med olika data som säger vad det är för typ av buss (år, kaross osv)
bussOwner = Innehåller ca 120 000 ägarebyten, Varje rad innehåller ett radbyte för fordonen i bussar (Datum, ÄgareID)
OwnerIndex = Innehåller ägarensnamn länkat med ÄgareID i bussOwner

Följande resultat önskar jag:
ID,Regnr,Senate ägarenamn, Chassitillverkare
1234,ABC123,Swebus AB, Volvo
1235,ABC124,Arriva AB, Volvo

Jag fastnar i följande SQL syntax

SELECT OwnerIndex.OwnerName, bussOwner.Vecorder, bussOwner.OwnerData, bussar.Registreringsnummer, bussar.Chassitillverkare, bussar.id, bussar.cbr_status FROM bussar INNER JOIN bussOwner ON bussar.id = bussOwner.VecID INNER JOIN OwnerIndex ON bussOwner.OwnerID = OwnerIndex.id WHERE (bussar.cbr_status < 40) ORDER BY bussOwner.VecID, Vecorder DESC

Istället för att sortera efter datum använder jag VecOrder där desto högre värde ger nyare ägare. Detta pågrund av att datum ibland är okänt på väldigt gamla fordon.

Ovanstående SQL syntax ger följande resultat: (Notera då att jag får samtliga ägare och varje fordon visas för varje ägare den haft tidigare från tabellen bussOwner
ID,Regnr,Senate ägarenamn, Chassitillverkare
1234,ABC123,Swebus AB, Volvo
1234,ABC123,Nobina AB, Volvo
1235,ABC124,Arriva AB, Volvo
1235,ABC124,Connex AB, Volvo

Är ingen jätte fena på SQL men någon duktigt "klocker" kan kanske ge mig ett steg i rätt riktning. Önskat läge är alltså att varje fordon skall bara visas en gång och att sista ägaren (Den med högst VecOrder nummer) visas tillsammans med fordonet.

//sammy
www.svenskbusshistoria.se

Permalänk
Medlem

Testa använda GROUP BY:

...GROUP BY bussar.Registreringsnummer

Permalänk
Medlem

..... LIMIT 1

Så får du ut en rad med den som är "högst" upp.

Antar att jag missuppfattat, så lätt kan det väl inte va?

Permalänk
Medlem
Skrivet av Garret:

Testa använda GROUP BY:

...GROUP BY bussar.Registreringsnummer

Måste man inte ha en aggregerande funktion då, typ MAX(date)? SQL-tänket är ganska abstrakt för mig

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Garret:

Testa använda GROUP BY:

...GROUP BY bussar.Registreringsnummer

Group by på bussar tabellen ger följande fel för mig:

Msg 8120, Level 16, State 1, Line 1 Column 'OwnerIndex.OwnerName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Inkluderar jag även GROUP BY på OwnerIndex och bussOwner så får jag exakt samma resultat som tidigare. Alltså den hämtar den hämtar samtliga ägare för varje fordon, även den som inte är aktuell. Bifogar en screenshot från outputen så kanske ni förstår bättre vad jag menar.

Exempelvis fordonet på med ID 1 vill jag skall bara förekomma en gång och endast med den ägare som har högst VecOrder nummer i detta fallet "Philipsons i Uppsala Bil AB, Uppsala"

Ovanstående resultat får jag genom följande SQL syntax

SELECT OwnerIndex.OwnerName, bussOwner.Vecorder, bussOwner.OwnerData, bussar.Registreringsnummer, bussar.Chassitillverkare, bussar.id, bussar.cbr_status FROM bussar INNER JOIN bussOwner ON bussar.id = bussOwner.VecID INNER JOIN OwnerIndex ON bussOwner.OwnerID = OwnerIndex.id WHERE (bussar.cbr_status < 40) GROUP BY OwnerIndex.OwnerName, bussOwner.Vecorder, bussOwner.OwnerData, bussar.Registreringsnummer, bussar.Chassitillverkare, bussar.id, bussar.cbr_status,bussOwner.VecID ORDER BY bussOwner.VecID, Vecorder DESC

Permalänk
Medlem
Skrivet av Kejsarn:

..... LIMIT 1

Så får du ut en rad med den som är "högst" upp.

Antar att jag missuppfattat, så lätt kan det väl inte va?

LIMIT verkar endast finnas för mySql. MSSQL ger bara incorrect syntax.

Permalänk
Medlem
Skrivet av sammyj:

LIMIT verkar endast finnas för mySql. MSSQL ger bara incorrect syntax.

Du kan använda TOP 1 för att bara får ett resultat i MSSQL, typ:

SELECT TOP 1 id FROM bussar

ger dig det första id-värdet.

Visa signatur

kill -s SIGCHLD `pidof Kenny`
bash: Oh my god, they killed Kenny
init: You Bastards

Permalänk
Medlem
Skrivet av houze:

Du kan använda TOP 1 för att bara får ett resultat i MSSQL, typ:

SELECT TOP 1 id FROM bussar

ger dig det första id-värdet.

Problemet är att jag bara får första vagnen i listan då alla andra 50 000 kommer ju inte med, Eller finns det något annat sätt att bara få det att verka på enna tabellen?

Permalänk
Medlem
Skrivet av sammyj:

Problemet är att jag bara får första vagnen i listan då alla andra 50 000 kommer ju inte med, Eller finns det något annat sätt att bara få det att verka på enna tabellen?

Testa SELECT DISTINCT..

edit: förresten, vad representerar Vecorder?

edit 2:

Det du vill göra är att köra MAX(vecorder) och GROUP BY regnr för att ta fram varje regnr och dess högsta vecorder. Det kan vara smidigt att göra detta i en separat query, eller så bakar man in det på något smart sätt som jag inte kommer på just nu...

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Testa SELECT DISTINCT..

edit: förresten, vad representerar Vecorder?

edit 2:

Det du vill göra är att köra MAX(vecorder) och GROUP BY regnr för att ta fram varje regnr och dess högsta vecorder. Det kan vara smidigt att göra detta i en separat query, eller så bakar man in det på något smart sätt som jag inte kommer på just nu...

VecOrder är ordningssiffran för ägarebytet eftersom vi inte alltid har ett fullständigt datum tillgängligt sorterar vi med denna istället. Se bilden nedan så förstår du kanske hur jag tänker. Ägaren jag vill hämta är den sista för varje fordon i detta fallet 2005-11-02 nettbuss med Ordning (VecOrder) 60.

Om jag använnder MAX(VecOrder) så kommer den ju inte att sortera ägarna rätt i tabellen endast cellen VecOrder kommer jag då det högsta värdet ifrån för varje fordon som visas i outputen.

Uppskattar din hjälp
//Sammy

Permalänk
Medlem

Du får nog köra en inner statement av något slag.

Ungefär så här lite snabbt skrivet utan eftertanke:

SELECT OwnerIndex.OwnerName, bussOwner.Vecorder, bussOwner.OwnerData, bussar.Registreringsnummer, bussar.Chassitillverkare, bussar.id, bussar.cbr_status FROM bussar INNER JOIN bussOwner ON bussar.id = bussOwner.VecID INNER JOIN OwnerIndex ON bussOwner.OwnerID = OwnerIndex.id WHERE (bussar.cbr_status < 40) and bussar.id = (select disctinct bussid from bussOwner order by Vecorder desc group by bussid ) ORDER BY bussOwner.VecID, Vecorder DESC

Visa signatur

En Laptop

Permalänk
Medlem
Skrivet av jurand:

Du får nog köra en inner statement av något slag.

Ungefär så här lite snabbt skrivet utan eftertanke:

SELECT OwnerIndex.OwnerName, bussOwner.Vecorder, bussOwner.OwnerData, bussar.Registreringsnummer, bussar.Chassitillverkare, bussar.id, bussar.cbr_status FROM bussar INNER JOIN bussOwner ON bussar.id = bussOwner.VecID INNER JOIN OwnerIndex ON bussOwner.OwnerID = OwnerIndex.id WHERE (bussar.cbr_status < 40) and bussar.id = (select disctinct bussid from bussOwner order by Vecorder desc group by bussid ) ORDER BY bussOwner.VecID, Vecorder DESC

Jag pillade lite i den fråga och då löste det sig faktiskt

Se nedan

SELECT OwnerIndex.OwnerName, bussOwner.Vecorder, bussOwner.OwnerData bussar.Registreringsnummer, bussar.Chassitillverkare, bussar.id, bussar.cbr_status FROM bussar INNER JOIN bussOwner ON bussar.id = bussOwner.VecID INNER JOIN OwnerIndex ON bussOwner.OwnerID = OwnerIndex.id WHERE (bussar.cbr_status < 40) AND bussOwner.id = (select top 1 id from bussOwner where VecID = bussar.id order by Vecorder desc) ORDER BY bussar.Registreringsnummer

Resultatet blir då precis som jag önskar!

Tack för er hjälp!
//Sammy