Hej jag håller på att porta en större databas från sybase => mssql, i sybase är denna fråga giltig: Mitt spontana förslag är väl att försöka dela upp det i mindre frågor (säg varje case i en mindre fråga), och sen använda where på det som återstår. Men det är mest för att göra det enklare att förstå. <b>select f as test from foo where test > 5</b> är visst giltigt i MSSQL. <b>>select f as test from foo where test > 5 är visst giltigt i MSSQL. ... mmmm om vi går på din linje så borde frågan skrivas som till: Och då återkommer vi till grundfrågan, eftersom "f" i det här fallet är en jävligt komplicerad beräkning. Alltså, gör som jag sa direkt; Var framgår det att det är en "jävligt komplicerad beräkning"? Kanske borde förtydliga mig lite, det gäller mssql 2005 och det korta exemplet (<b>select f as test from foo where test > 5</b>) fungerar inte alls för mig. Pontus, finns det en kolumn som heter test i tabellen foo, Jodå ditt exempel fungerar fint men scenariot är så här: ... ska åka och bada kidsen i sjön, återkommer ikväll. <code> <b>Men kan du inte helt enkelt först ta ut alla delar du är intresserad av, och sen göra nya hopslagningar i en yttre fråga?</b> <b>Som jag skrev tidigare så kan man inte använda ett alias som skapas i selecten (t) i where uttrycket.</b> [snabbt (nästan)] Känner att jag inte lyckats vara helt tydlig från start och det ställer till sig lite, låt oss börja om från början så kan jag istället förklara vad jag vill göra: Hej Pontus, Och då måste väl det enklaste ändå vara mitt förslag: Intressant, detta ska jag pröva på. Niklas variant är också bra men har nackdelen av att vara svårläst. Stort tack till er båda...Kan inte använda alias
<code>select f as test from foo where test > 5</code>
och att det inte är giltigt i mssql har jag förstått men en av frågorna jag har ser ut så här:
<code>
select g.mpid,
g.pside,
case mpdir
when 0 then mp.x
when 1 then mp.x+dsax-ps
when 2 then mp.x
when 3 then mp.x
when 4 then mp.x-dsax+ps
when 5 then mp.x
when 51 then mp.x
end as gx,
case mpdir
when 0 then mp.y
when 1 then mp.y
when 2 then mp.y+dsax-ps
when 3 then mp.y-dsax+ps
when 4 then mp.y
when 5 then mp.y
when 51 then mp.y
end as gy,
case mpdir
when 0 then mp.zmont+dsaz+t.size-ps
when 1 then mp.zmont+dsaz+t.size
when 2 then mp.zmont+dsaz+t.size
when 3 then mp.zmont+dsaz+t.size
when 4 then mp.zmont+dsaz+t.size
when 5 then mp.zmont-dsaz-t.size+ps
when 51 then mp.zmont-dsaz+t.size+ps
end as gzmont,
case mpdir
when 0 then mp.zdemont+dsaz+t.size-ps
when 1 then mp.zdemont+dsaz+t.size
when 2 then mp.zdemont+dsaz+t.size
when 3 then mp.zdemont+dsaz+t.size
when 4 then mp.zdemont+dsaz+t.size
when 5 then mp.zdemont-dsaz-t.size+ps
when 51 then mp.zdemont-dsaz+t.size+ps
end as gzdemont,
dsa.x + isnull((select sum(x)
from ds_adapter as ddsa
where ddsa.adapterid = any(
select adapterid from mpadapter as mpa where mpa.mpid = mp.mpid)),0) as dsax,
dsa.y + isnull((select sum(y)
from ds_adapter as ddsa
where ddsa.adapterid = any(
select adapterid from mpadapter as mpa where mpa.mpid = mp.mpid)),0) as dsay,
dsa.z + isnull((select sum(z)
from ds_adapter as ddsa
where ddsa.adapterid = any(
select adapterid from mpadapter as mpa where mpa.mpid = mp.mpid)),0) as dsaz,
case when g.ptobjectsize > 99
then g.ptobjectsize/100
else g.ptobjectsize
end as psps,
case when(g.pointobjectid < 4) or(g.pointobjectid = 9)
then
case when(mp.adapterid >= 16 and mp.adapterid <= 19) or (mp.adapterid >= 21 and mp.adapterid <= 24) or (mp.adapterid >= 41 and mp.adapterid <= 44) or (mp.adapterid >= 46 and mp.adapterid <= 46) then
psps/2
when(mp.adapterid >= 59 and mp.adapterid <= 64) or (mp.adapterid >= 66 and mp.adapterid <= 69) then
0
else psps
end
else psps
end as ps,
case when hno <= 200 and mp.dir = 5 then 51
else mp.dir
end as mpdir
from gdsmp as g
join mpoint as mp on mp.mpid = g.mpid
join ds_adapter as dsa on mp.adapterid = dsa.adapterid
join pointobject as po on po.pointobjectid = g.pointobjectid
join ds_tube as t on t.tube = mp.tube
where hno = 19
and sno = 20
and sheet = 1
and g.pointobjectid > 0
and g.ptobjectsize > -1
</code>
Har någon ett bra förslag på hur jag ska lösa det? Frågan i sig är dessutom en del i en cursor, om det påverkar saker från illa till värre....Sv: Kan inte använda alias
Du kan ju översätta din första fråga:
<code>select f as test from foo where test > 5</code>
till
<code>select test from (select f as test from foo) where test > 5</code>
Hajar inte riktigt hur cursor-biten skulle leda till problem i det här fallet.Sv: Kan inte använda alias
Förutsatt att det finns en tabell vid namn foo och den har fälten/kolumnerna test och f.
Angående det andra kodstycket så ser det syntaxmässigt helt ok ut (bara att klistra in...).
(Kan ha missat något inte helt lätt att följa).
Däremot så "saknas" det en del alias på vissa fält/kolumner.
T.ex här:
<b>where hno = 19
and sno = 20
and sheet = 1</b>
Dessa borde se ut så här om de hör till gdsmp
<b>where g.hno = 19
and g.sno = 20
and g.sheet = 1</b>
o.s.v.
Om det inte finns fält med samma namn i andra tabeller så funkar det ändå.
Men det blir lättare att logiskt se var dom hör hemma.
/HåkanSv:Kan inte använda alias
Förutsatt att det finns en tabell vid namn foo och den har fälten/kolumnerna test och f. </b>
Men nu byter han namn på "f" till "test" i själva anropet. foo har alltså ingen kolumn test.Sv: Kan inte använda alias
<code>
SELECT f AS test FROM foo WHERE f > 5
</code>
Svaret är då att man inte kan använda alias på fälten från SELECT i WHERE.
Enda stället man kan använda dom är i ORDER BY (om jag minns rätt.)
Gäller förstås MSSQL.
/HåkanSv:Kan inte använda alias
SELECT test FROM (SELECT f AS test FROM foo) WHERE test > 5
Minimal förändring av koden nödvändig.Sv: Kan inte använda alias
Jag har missat det.
Ditt exempel fungerar inte (inte i MSSQL iaf).
Ska skrivas så här (om jag har förstått dig rätt):
<code>
SELECT test FROM (SELECT f AS test FROM foo WHERE test > 5) a;
</code>
Känns inte enklare än att ändra ett fältnamn från test till f.
Men, men jag har väl inte hela bilden klar för mig.
/HåkanSv:Kan inte använda alias
Angående:
<b>where g.hno = 19
and g.sno = 20
and g.sheet = 1</b>
Visst för tydlighetens skull så borde man göra så, men rent tekniskt för frågan i sig har det ingen betydelse...Sv: Kan inte använda alias
eller refererar det till aliaset som görs i SELECTen?
Se även min och Niklas diskussion ovan.
Bifogar ett exempel för detta, som fungerar i MSSQL 2005, och som går att diskutera vidare runt:
<code>
CREATE TABLE foo
(
f int,
test int
);
INSERT INTO foo VALUES (1, 6);
INSERT INTO foo VALUES (2, 4);
INSERT INTO foo VALUES (3, 7);
SELECT f AS test FROM foo WHERE test > 5;
DROP TABLE foo;
</code>
/HåkanSv:Kan inte använda alias
<code>
CREATE TABLE foo
(
f int,
test int
);
INSERT INTO foo VALUES (1, 4);
INSERT INTO foo VALUES (2, 5);
INSERT INTO foo VALUES (3, 6);
-- Fungerar inte:
-- Msg 207, Level 16, State 1, Line 10
-- Invalid column name 't'.
SELECT (case f when 1 then NULL else 1 end) AS t
FROM foo
WHERE t is not null;
-- Fungerar fint beroende på att jag skapat t i min subquery
SELECT t
FROM (select (case f when 1 then NULL else 1 end) AS t from foo) as subquery_foo
WHERE t is not null;
-- Problemet jag har är att nu när jag har t så vill jag "prata med" t och även den nytillkomna b som är beroende av t:
-- Fungerar finemang:
SELECT t,
(case t when 2 then NULL else 9 end) AS b
FROM (select (case f when 1 then NULL else 1 end) AS t from foo) as subquery_foo
WHERE t is not null;
-- Fungerar inte:
-- Msg 207, Level 16, State 1, Line 3
-- Invalid column name 'b'.
SELECT t,
(case t when 2 then NULL else 9 end) AS b,
(b + t) as result -- Så här vill jag göra ett antal gånger till fast med korsreferenser på flera alias vilket gör att....
FROM (select (case f when 1 then NULL else 1 end) AS t from foo) as subquery_foo --... den här lösningen kommer att generera på tok för många subquerys att skriva, då den frågan jag utgått ifrån är flera ggr större än det som jag beskrivit
WHERE t is not null;
DROP TABLE foo;
</code>Sv: Kan inte använda alias
Men tillsvidare:
Som jag skrev tidigare så kan man inte använda ett alias som skapas i selecten (t) i where uttrycket.
/Håkan Sv: Kan inte använda alias
SELECT t,
(case t when 2 then NULL else 9 end) AS b,
(b + t) as result -- Så här vill jag göra ett antal gånger till fast med korsreferenser på flera alias vilket gör att....
FROM (select (case f when 1 then NULL else 1 end) AS t from foo) as subquery_foo --... den här lösningen kommer att generera på tok för många subquerys att skriva, då den frågan jag utgått ifrån är flera ggr större än det som jag beskrivit
WHERE t is not null;
</code>
Men kan du inte helt enkelt först ta ut alla delar du är intresserad av, och sen göra nya hopslagningar i en yttre fråga?
<code>
SELECT t, b, b+t as result, b*b - t as result2, ... FROM (
SELECT t,
(case t when 2 then NULL else 9 end) AS b,
FROM (select (case f when 1 then NULL else 1 end) AS t from foo) as subquery_foo
WHERE t is not null);
</code>
För som jag förstår det har du ett antal "genererade" variabler a,b,c, osv. som du sen slår ihop för att få svar ifrån. Om du bara först genererar a,b,c, osv. i en fråga, så kan du ju slå ihop i nästa steg?
Eller menar du att du kommer få ett djup sekvens med frågor om du gör så?
Att alla ska bero på föregående? För så ser det inte ut.Sv:Kan inte använda alias
Det har du rätt i, ska försöka generera frågan på det viset. Tyvärr så skulle problematiken lösas enkelt om man som i oracle kunde sätta globala alias på tabeller och frågor men det lär nog inte hända i mssql-världen....Sv:Kan inte använda alias
Som du ser använder jag det inte i where-uttrycket i första hand, det primära stället jag behöver ha det på är i selectsatsen som en andel av ett annat resultat.Sv: Kan inte använda alias
... njaaa nu håller jag inte med dig.
Ordets makt över tanken, utifrån hur du uttrycker dig.
Du skrev:
>><b>Som du ser använder jag det inte i where-uttrycket i första hand, det primära stället jag behöver ha det på är i selectsatsen som en andel av ett annat resultat.</b>
Ja om du inte tänkt använda det i WHERE, då ordnar det sig (en massa olika varianter står till buds).
>><b>man som i oracle kunde sätta globala alias på tabeller och frågor </b>
I ditt exempel ovan skrev du:
<code>
SELECT t
FROM (select (case f when 1 then NULL else 1 end) AS t from foo) as subquery_foo
WHERE t is not null;
</code>
Här ovan har du precis gjort det som du senare skrev att man inte kan i MSSQL
,nämligen sätta alias på en fråga, när du ger frågan ett alias "as as subquery_foo".
Man kan nu referera till reultatet från frågan överallt med aliaset subquery_foo. T.ex subquery_foo.t
Självklart kan man sätta alias på tabeller också t.ex.
<code>SELECT * FROM foo AS footable</code>
Där footable är alias på tabellen.
Du menar nog något annat...
/HåkanSv:Kan inte använda alias
Jag vill selektera ett eller flera värden från en eller flera tabeller, dessa värden kommer redan i sql-frågan att manipuleras beroende på vad de innehåller (mha case-satser) och tilldelas alias, vidare vill jag skapa andra värden utifrån dels det resultatet som respektive alias innehåller och tilldela dessa nya värden alias. Alltså så här (fast betydligt mera komplext):
<code>
-- Tabell Foo innehåller fälten a int, b int
-- Om b = 5 så ska det presenteras som 1 annars som 2 med namnet C
-- Utanpå detta vill jag addera ihop C och b och presentera det som D
-- Vidare vill jag att kolumnen E ska innehålla NULL om D = 5 annars ska den innehålla 0
select a, (case b when 5 then 1 else 2 end) as C, (C + b) as D, (case D when 5 then NULL else 0 end) as E
from Foo
</code>
Detta är en giltig syntax och förfarande i Oracle och i Sybase (från vilken jag portar en databas innehållandes över 900 procedurer, jag får dessutom inte semester innan jag är färdig...) men inte i MSSQL, min konkreta fråga (så konkret jag kan ställa den) är: Finns det något annat mer vedertaget sätt att göra detta på än att bygga kollosala subquerys i MSSQL 2005?
I normala fall hade jag faktiskt valt att lagra datat lite redundant i databasen men det är inte gångbart alternativ i det här fallet, vidare är det ganska många procedurer som använder den här typen av frågor med större eller mindre komplexitet i den databas jag portar.Sv: Kan inte använda alias
Lessen att jag inte svarat tidigare, sommar och semester, vilket du tyvärr inte verkar få...
Det konkreta svaret på din konkreta fråga (nu när jag äntligen förstår) är, nej det finns inget annat sätt att göra detta på.
Det finns en ny feature i 2005an som jag tycker är rätt trevlig Common Table Expression (CTE).
Med hjälp av dom kan man bryta ner komplexa frågor till små mindre steg.
Personligen så tycker jag att dom också ger ett rätt trevlig flöde i koden.
Varje CTE tar hand om en lite (eller större) del.
Men det ger mer kod, än tidigare.
Ett exempel på det som vi tidgare skrev om ovan blir då (tabellen foo):
<code>
;WITH CTE1 AS
(
SELECT
a,
b,
(CASE b WHEN 5 THEN 1 ELSE 2 END) AS c
FROM foo
),
CTE2 AS
(
SELECT
a,
b,
c,
(c + b) AS d
FROM CTE1
)
SELECT
a,
b,
c,
d,
(CASE d WHEN 5 THEN NULL ELSE 0 END) AS e
FROM CTE2;
</code>
/HåkanSv: Kan inte använda alias
SELECT a, C, D, (case D when 5 then NULL else 0 end) as E FROM(
SELECT a, C, (C + b) as D FROM
(SELECT a, b, (case b when 5 then 1 else 2 end) as C FROM Foo)
)
)
Allt annat (where, group by, osv.) läggs i "yttersta frågan". Det är väldigt straightforward, kommer ge en del extra kod, men inte jättemycket, och fungerar på alla (?) databaser.Sv:Kan inte använda alias