PDA

Vollständige Version anzeigen : Grundlegende SQL Probleme


strausto
05.08.2007, 20:26
Aufgabe:

Anzeigen alle Datensätze je Gruppe (col2) die jünger sind als der älteste Datensatz inklusive aller anderen Informationen des Tupels (hier inklusive der ID).

Tabelle (Ausgangsituation)

id col1 col2
1 01.01.2007 00:00 1
2 01.01.2007 00:00 1
3 31.12.2006 00:00 1
4 11.06.2007 00:00 2
5 23.09.2007 00:00 2
6 01.01.2006 00:00 2
7 05.12.2007 00:00 3
8 06.12.2007 00:00 3
9 13.04.2007 00:00 4


Ausgabe

id col1 col2
1 01.01.2007 00:00 1
2 01.01.2007 00:00 1
3 31.12.2006 00:00 1
4 11.06.2007 00:00 2
5 23.09.2007 00:00 2
6 01.01.2006 00:00 2
7 05.12.2007 00:00 3
8 06.12.2007 00:00 3
9 13.04.2007 00:00 4



Tabellendefinition

use tempdb

Go

if object_id(N'tempdb.dbo.Table1',N'U') is not null
drop table Table1
create table Table1
(
id int Not Null identity(1,1)
,col1 smalldatetime Not Null
,col2 int Not Null
)

Go
Insert tempdb.dbo.Table1 (col1,col2) Select '20070101',1
Insert tempdb.dbo.Table1 (col1,col2) Select '20070101',1
Insert tempdb.dbo.Table1 (col1,col2) Select '20061231',1
Insert tempdb.dbo.Table1 (col1,col2) Select '20070611',2
Insert tempdb.dbo.Table1 (col1,col2) Select '20070923',2
Insert tempdb.dbo.Table1 (col1,col2) Select '20060101',2
Insert tempdb.dbo.Table1 (col1,col2) Select '20071205',3
Insert tempdb.dbo.Table1 (col1,col2) Select '20071206',3
Insert tempdb.dbo.Table1 (col1,col2) Select '20070413',4


Erster Ansatz:


select
[MIN(col1)] = min(col1),
col2
from
tempdb.dbo.Table1
group by
col2


Resultset:


MIN(col1) col2
31.12.2006 00:00 1
01.01.2006 00:00 2
05.12.2007 00:00 3
13.04.2007 00:00 4



Problem:

Es wird sehr wohl ausschließlich nur der älteste Datensatz je Gruppe (col2) ausgewertet nur bezieht das Ergebnis nicht alle Informationen ein (ID).

Erneuter Versuch:


select
min(col1),
col2,
id
from
tempdb.dbo.Table1
group by
col2


Fehler:
Die 'tempdb.dbo.Table1.id'-Spalte ist in der Auswahlliste ungültig, da sie nicht in einer Aggregatfunktion und nicht in der GROUP BY-Klausel enthalten ist.



Lösung


select
T1.*
from
tempdb.dbo.Table1 T1
inner join
(
select
col1 = min(col1),
col2 = col2
from
tempdb.dbo.Table1
group by
col2
) T2
on
T1.col2 = T2.col2
AND T1.col1 = T2.col1



Resultset


id col1 col2
3 31.12.2006 00:00 1
6 01.01.2006 00:00 2
7 05.12.2007 00:00 3
9 13.04.2007 00:00 4

strausto
28.10.2007, 19:53
Probleme bei der Berechnung innerhalb eines Selects

Aufgabe

Ermittlung des Quotienten aus 5 / 2

erster Ansatz

Select 5 / 2


Ergebnis

2


Warum wird nun 2 anstelle von 2.5 als Quotient angezeigt?

Dieser Umstand geht auf die Rangfolge der Datentypen zurück:

Wenn durch einen Operator zwei Ausdrücke verschiedener Datentypen
kombiniert werden, geben die Rangfolgeregeln für Datentypen an, dass der
Datentyp mit der niedrigeren Rangfolge in den Datentyp mit der höheren
Rangfolge konvertiert wird. Wenn es sich bei der Konvertierung nicht um eine
unterstützte implizite Konvertierung handelt, gibt das System einen Fehler
zurück. Wenn beide Operandenausdrücke vom gleichen Datentyp sind, hat
das Ergebnis der Operation diesen Datentyp.

SQL Server 2005 verwendet die folgende Rangfolge für Datentypen:

benutzerdefinierte Datentypen (höchster)

sql_variant
xml
datetime
smalldatetime
float
real
decimal
money
smallmoney
bigint
int
smallint
tinyint
bit
ntext
text
image
timestamp
uniqueidentifier
nvarchar
nchar
varchar
char
varbinary
binary (niedrigster)


In unserem Beispiel werden zwei Integer Werte miteinander dividiert - folglich ist das Ergebnis ebenfalls vom Typ Integer. Es wird dabei keinerlei Rundung vorgenommen, sondern die Ziffern nach dem Komma abgeschnitten.

Um das richtige Resultat zu erhalten, muss wenigstens ein Operator als Decimal bestimmt sein.


Select 5 / 2.0
Ergebnis

2.5
Decimal steht in der Hierarchie über Integer demzufolge ist das Ergebnis ebenfalls vom Typ Decimal.

Sollen nun zwei Spalten innerhalb einer Tabelle dividiert werden, die als Integer definiert sind, empfiehlt sich folgendes:
DECLARE @Table TABLE (col1 INT, col2 INT)
INSERT @Table SELECT 5,2
INSERT @Table SELECT 2,5
SELECT 1.0 * col1 / col2 FROM @Table
Ergebnis

2.500000000000
0.400000000000

Durch das Konvertieren des Hilfsoperators in Money, wird das Resultset ebenfalls in Money konvertiert:
(Money steht in der Hierarchie über Integer)
DECLARE @Table TABLE (col1 INT, col2 INT)
INSERT @Table SELECT 5,2
INSERT @Table SELECT 2,5
SELECT convert(money,1) * col1 / col2 FROM @Table
Ergebnis

2,50
0,40
(Ich habe die dt. Länderspezifikation eingestellt, daher das Komma anstelle des Punktes)