Sida 1 av 1
Ännu en SQL-Fråga
Postat: 13 mars 2010, 14:00:44
av Gildebrand
Hejsan!
Jag har lyckats göra en SQL-Fråga med hjälp av lite internet-guider. Såhär ser den ut:
Kod: Markera allt
declare @listcol nvarchar(max)
declare @query nvarchar(max)
select @listcol = STUFF(( Select distinct
'],[' + LTRIM(str(Subject_ID))
from Ämnen i
left join Subjects S
on i.Subject_ID=S.ID
FOR XML PATH('')
), 1, 2, '') + ']'
set @query =
'SELECT *
FROM (
SELECT Elev_ID, Subject_ID, Teacher_ID
FROM Ämnen) myTemp
PIVOT (count(Teacher_ID) FOR Subject_ID
IN (' +@listcol+')) AS pvt
order by Elev_ID'
execute (@query)
Resultatet på frågan kan se ut såhär:
Kod: Markera allt
Elev_ID 10 13 14 15 16 2 3 4 6
0687B0C9-9454-4DE5-AF41-077EB10BCD81 0 0 1 0 0 0 0 0 0
B4BEB520-5F57-4B31-9DD4-0F580B84B752 0 0 0 0 0 0 0 0 0
8F34753E-FE45-40AD-B51A-4A5C493B494C 0 0 0 0 0 0 0 0 0
Nu är det tre saker kvar som jag vill få till, som jag haft problem att lyckas med.
- 1. Använda mig av Left Join för att kunna presentera Subject istället för Subject_ID. I frågan ovan har jag lagt till en left join, men när jag provar att byta ut Subject_ID mot S.Subject så får jag "Error converting data type nvarchar to float."
2. I Pivotfunktionen räknar jag ju bara hur många lärare som finns för eleven, men jag vill istället presentera ett UniqueID för den första läraren som hittas för eleven. Jag har provat att byta ut count(Teacher_ID) mot Min(Cast(Teacher_ID as NVARCHAR(max))), får då error också, "Msg 102, Level 15, State 1, Line 5
Incorrect syntax near '('."
3. Sortera kolumnerna efter dess ID, har provat "ORDER BY '],[' + ltrim(str(Subject_ID))", men det påverkar ingenting alls faktiskt.
[/list]
Re: Ännu en SQL-Fråga
Postat: 13 mars 2010, 14:17:21
av sodjan
> men när jag provar att byta ut Subject_ID mot S.Subject...
Visa den nya queryn. Det är lite svårt (och helt onödigt) att
försöka gissa vad du har gjort.
> så får jag "Error converting data type nvarchar to float."
Och det är inte uppenbart från din query varför det blir så ?
Det verkar som att du blandar datatyper på ett sätt som inte går.
Beroende på hur queryn nu ser ut så kanske en CAST fixar det.
Sen så skulle en tabellbeskrivning vara användbart.
Slutligen så skulle jag undvika åäö i namn på tabeller o.s.v.
Det är möjligt att det fungerar, men i alla fall...
Re: Ännu en SQL-Fråga
Postat: 13 mars 2010, 14:28:46
av Gildebrand
Kod: Markera allt
declare @listcol nvarchar(max)
declare @query nvarchar(max)
select @listcol = STUFF(( Select distinct
'],[' + LTRIM(str(S.Subject))
from Ämnen i
left join Subjects S
on i.Subject_ID=S.ID
ORDER BY '],[' + ltrim(str(S.Subject))
FOR XML PATH('')
), 1, 2, '') + ']'
set @query =
'SELECT *
FROM (
SELECT Elev_ID, Subject_ID, Teacher_ID
FROM Ämnen) myTemp
PIVOT (count(Teacher_ID) FOR Subject_ID
IN (' +@listcol+')) AS pvt
order by Elev_ID'
execute (@query)
Resulterar i
Kod: Markera allt
Error converting data type nvarchar to float.
Provade också att byta ut LTRIM(STR(S.Subject)) mot LTRIM(S.Subject), vilket resulterar i
Kod: Markera allt
Msg 8114, Level 16, State 1, Line 6
Error converting data type nvarchar to int.
Msg 473, Level 16, State 1, Line 6
The incorrect value "Biologi" is supplied in the PIVOT operator.
Re: Ännu en SQL-Fråga
Postat: 13 mars 2010, 16:35:53
av sodjan
OK, det skulle underlätta väldigt mycket om du kan visa hur de berörda tabellerna
är definierade. Det är ju helt uppbart att du blandar datatyper på ett sätt som
inte är OK. Det är ju exakt det som felmeddelandet säger. Hitta det och fixa det.
Jag *antar* att "Subject_ID" är ett numeriskt värde och att "Subject" är en sträng.
Och då är det ju även ganska uppenbart att du inte bara rakt av kan byta det
ena mot det andra hur som helst.
Re: Ännu en SQL-Fråga
Postat: 14 mars 2010, 00:49:07
av Gildebrand
Då ska vi se så att jag får med allt här då. Jag kommer att stryka en del helt irrelevanta kolumner för enkelhetens skull.
Ämnen:
Kod: Markera allt
Elev_ID, UniqueIdentifier
Teacher_ID, UniqueIdentifier
Subject_ID, Int
Här är ett utdrag ur tabellen Ämnen, för läslighetens skull kortar jag ner alla Unique-Identifier, men så du vet att de egentligen är längre.
Kod: Markera allt
ID Elev_ID Teacher_ID Subject_ID
FA01 0687 NULL 2
9F08 0687 NULL 4
4618 0687 NULL 3
5BFA B4BE NULL 3
554E B4BE NULL 4
713D B4BE NULL 2
E724 8F34 NULL 3
465B 8F34 NULL 4
5DEC 8F34 5A5E 2
I tabellen Subjects "deklareras" alla ämnen och dess ID.
Där kolumnen Subject, är av datatypen nvarchar(50), och kolumnen ID av datatypen int.
Ett utdrag ur Subjects:
Kod: Markera allt
Subject ID
Matte 2
Engelska 3
Idrott och Hälsa 4
Målet med SQL-Frågan ska vara att få ut något som ser ut såhär:
Kod: Markera allt
Elev_ID Matte Engelska Idrott och Hälsa
0687 NULL NULL NULL
B4BE NULL NULL NULL
8F34 5A5E NULL NULL
Hoppas jag varit tydlig nog med vad jag vill nu.
Re: Ännu en SQL-Fråga
Postat: 14 mars 2010, 01:45:33
av sodjan
OK.
Har du funderat mer på var du får "krocken" mellan nvarchar och int/float ?
I PIVOT har du "FOR Subject_ID IN (' +@listcol+'))" där Subject_ID är en int och det som
står i IN(...) är det som returneras från din "@listcol" funktion, eller hur ? Och
det är väl en radda med nvarchar's, är det inte det ? När du har en "for abc in (x, y, z) så
måste abc och x, y och x ha matchande datatyp.
Dessutom är ju inte testet rellevant ändå, eftersom det ena är rubriken på ämnet
och det andra är ID för ämnet, de kommer i alla fall aldrig att få träff, även om du
t.ex omvandlar ID till en nvarchar så att felet (eventuellt) försvinner.
Så det verkar lite feltänkt det hela. Eller otillräckligt tänkt...
Ett annat problem med din lösning är att du får ett resultat med olika antal
kolumner beroende på vilka ämnen som du får träff på. Det är inte så snyggt
ur ren SQL synvinkel, men vill oftast ha ett visst utseende på kolumnerna tillbaka,
d.v.s antal och datatyp (men naturligstvis olika *antal* poster beroende på träffarna).
Re: Ännu en SQL-Fråga
Postat: 14 mars 2010, 02:57:38
av Gildebrand
Ska försöka förstå allt det där när jag är i ett litet mera vaket tillstånd, men nu så tänkte jag bara rapportera om att jag har lyckats med en liten bit. Att presentera ett UniqueID istället för bara count.
Såhär vart frågan:
Kod: Markera allt
set @query =
'SELECT *
FROM (
SELECT Elev_ID, Subject_ID, cast(Teacher_ID as nvarchar(max)) as Teacher_ID
FROM Ämnen) myTemp
PIVOT (Max(Teacher_ID) FOR Subject_ID
IN (' +@listcol+')) AS pvt
order by Elev_ID'
execute (@query)
Så det verkar lite feltänkt det hela. Eller otillräckligt tänkt...

Det är inte jag som har tänkt, det är internet

Re: Ännu en SQL-Fråga
Postat: 14 mars 2010, 09:52:54
av sodjan
> Det är inte jag som har tänkt, det är internet
OK, men då får du ge även de referenserna, så att
det går att följa "tänket". Eller är det hemligt ?
Re: Ännu en SQL-Fråga
Postat: 14 mars 2010, 12:11:03
av Gildebrand
http://www.sqlprof.com/blogs/sqldev/arc ... -2008.aspx
Jag har använt mig av frågan som står under "Now, all we have to do is to convert our pivot into a dynamic query:", och anpassat den lite grann för att passa mig.
Re: Ännu en SQL-Fråga
Postat: 14 mars 2010, 13:13:35
av sodjan
OK.
Vad som inte framgår där är vilken datatyp som "OrderYear" har.
Men den har sannolikt en datatyp som matchar den @listcol som
genereras, alltså sannolikt en char (av något slag). Och dessutom så
jämför de ju äpplen med äpplen (alltså OrderYear mot en lista med Year).
Men ditt felmeddelande är ju tydligt nog.
Och du har inte ännu svarat på hur du tänkte när du jämför
"Subject_ID" mot en lista med "Subject". Det kan ju aldrig få
träff i alla fall. Det blir lite äpplen och päron...
Re: Ännu en SQL-Fråga
Postat: 14 mars 2010, 15:54:51
av Gildebrand
Med följande fråga kan jag ju få ut unika ämnen med dess namn och inte ID.
Kod: Markera allt
select distinct S.Subject from Ämnen i
left join Subjects S
ON i.Subject_ID=S.ID
Det är istortsett samma sak som jag vill göra i denna fråga
Kod: Markera allt
select @listcol = STUFF(( Select distinct
'],[' + LTRIM(str(Subject_ID))
from IUP i
left join Subjects S
on i.Subject_ID=S.ID
FOR XML PATH('')
), 1, 2, '') + ']'
Så man kan tänka sig att jag byter ut Subject_ID i ovanstående fråga mot S.Subject.
Men är du med på vad jag är ute efter?
Re: Ännu en SQL-Fråga
Postat: 14 mars 2010, 16:08:00
av sodjan
Den där SQL'en har inga problem, du jämför ju ID med ID i "ON i.Subject_ID=S.ID"
Alltså integer med integer, inga problem alls och helt normalt. Att du har med
strängen Subject i resultatet är i det sammanhanget komplett ointressant.
Problemet är att den där @listcol skapar alltså en lista med *strängar* (eller hur ?)
som senare används i en "FOR Subject_ID IN (' +@listcol+'))" där Subject_ID är
en integer, därav felet. Om jag inte har missat något.
Du kan t.ex inte göra "for <some-integer> in ('abc', 'def', 'ghj')"
D.v.s så som du försöker göra.
Däremot är "for <string> in ('abc', 'def', 'ghj')" helt OK.
Dessutom så kommer du i alla fall aldrig att få träff eftersom Subject och
Subject_ID aldrig innehåller samma sak.
Om jag är med på vad du vill göra ? Tja, ungefär, tror jag...

Jag är inte speciellt intresserad av slutresultatet igentligen, jag
försöker bara förklara vad du gör fel...