[T-SQL] NULL als record niet bestaat

Pagina: 1
Acties:

  • Slagroom
  • Registratie: Juni 2001
  • Laatst online: 05-10-2024
Ik ben bezig met het ontwikkelen van een programma en merk dat een JOIN niet mijn sterkste kant is.

Ik heb de volgende code:
SQL:
1
2
3
4
5
6
7
SELECT     TOP (100) PERCENT Modified, HorseId,
                          (SELECT     TOP (1) OwnerId
                            FROM          dbo.HorseOwner
                            WHERE      (HorseId = dbo.HorseVersion.HorseId) AND (Modified = dbo.HorseVersion.Modified) AND (OwnerId = 1)) AS OwnerId
FROM         dbo.HorseVersion
WHERE     (HorseId = 1)
ORDER BY Modified

Die geeft het gewenste resultaat, namelijk:
code:
1
2
3
4
5
6
7
8
9
10
11
12
Modified                HorseId     OwnerId
----------------------- ----------- -----------
2006-10-20 10:00:00.000 1           1
2006-11-03 12:26:33.733 1           1
2006-11-04 00:12:22.280 1           1
2006-11-06 00:00:00.000 1           1
2006-11-09 00:00:00.000 1           1
2006-11-17 00:00:00.000 1           1
2006-11-30 00:00:00.000 1           NULL
2006-12-01 00:00:00.000 1           1

(8 row(s) affected)


Maar als ik JOINS denk te begrijpen, zou hij het zelfde resultaat toch ook met een LEFT JOIN moeten geven. Deze query:
SQL:
1
2
3
4
5
6
SELECT     TOP (100) PERCENT dbo.HorseVersion.Modified, dbo.HorseVersion.HorseId, dbo.HorseOwner.OwnerId
FROM         dbo.HorseVersion LEFT JOIN
                      dbo.HorseOwner ON dbo.HorseVersion.HorseId = dbo.HorseOwner.HorseId AND dbo.HorseVersion.Modified = dbo.HorseOwner.Modified
WHERE     (dbo.HorseVersion.HorseId = 1) AND (dbo.HorseOwner.OwnerId = 1 OR
                      dbo.HorseOwner.OwnerId IS NULL)
ORDER BY dbo.HorseVersion.Modified


Maar die geeft alleen de records weer uit dbo.HorseVersion die ook een gelijke record (dbo.HorseOwner ON dbo.HorseVersion.HorseId = dbo.HorseOwner.HorseId AND dbo.HorseVersion.Modified = dbo.HorseOwner.Modified) in dbo.HorseOwner heeft. En dat wil ik juist niet. Hij moet ook de records uit dbo.HorseVersion laten zien zonder gelijke record uit dbo.HorseOwner. Dit is het resultaat van bovenstaande query:
code:
1
2
3
4
5
6
7
8
9
10
11
Modified                HorseId     OwnerId
----------------------- ----------- -----------
2006-10-20 10:00:00.000 1           1
2006-11-03 12:26:33.733 1           1
2006-11-04 00:12:22.280 1           1
2006-11-06 00:00:00.000 1           1
2006-11-09 00:00:00.000 1           1
2006-11-17 00:00:00.000 1           1
2006-12-01 00:00:00.000 1           1

(7 row(s) affected)


Het uiteindelijke doel van deze query is om te kijken welke periode een Owner een Horse in bezit heeft gehad. Dit kan met tussenpauzes.

Is de eerste query niet een enorme aanslag op de performance? Waarom werkt de JOIN niet. Kortom... waar ga ik de mist in?

Alvast enorm bedankt!

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
In de 2e query staat helemaal geen left join :?

Oops! Google Chrome could not find www.rijks%20museum.nl


  • Slagroom
  • Registratie: Juni 2001
  • Laatst online: 05-10-2024
Pardon, oude query. Bedankt voor de tip. Het resultaat is het zelfde :)

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Weet je 100% zeker dat die 2e query het niet goed doet? Ik kan er geen fouten in ontdekken, de query zou het volgens mij moeten doen.

Oops! Google Chrome could not find www.rijks%20museum.nl


  • PhysicsRules
  • Registratie: Februari 2002
  • Laatst online: 31-03 07:26

PhysicsRules

Dux: Linux voor Eenden

Heb je al getest wat er gebeurd als je de WHERE weglaat. Komen er dan wel NULL's tevoorschijn?

  • Slagroom
  • Registratie: Juni 2001
  • Laatst online: 05-10-2024
P_de_B schreef op donderdag 30 november 2006 @ 08:48:
Weet je 100% zeker dat die 2e query het niet goed doet? Ik kan er geen fouten in ontdekken, de query zou het volgens mij moeten doen.
Hij geeft niet het resultaat wat ik wil dat hij geeft (zie 1e query startpost). Misschien zie ik het helemaal verkeerd of denk ik de verkeerde kant op...

De volgende query (zonder where)
SQL:
1
2
3
4
SELECT     TOP (100) PERCENT dbo.HorseVersion.Modified, dbo.HorseVersion.HorseId, dbo.HorseOwner.OwnerId
FROM         dbo.HorseVersion LEFT JOIN
                      dbo.HorseOwner ON dbo.HorseVersion.HorseId = dbo.HorseOwner.HorseId AND dbo.HorseVersion.Modified = dbo.HorseOwner.Modified
ORDER BY dbo.HorseVersion.Modified

Geeft dit als resultaat:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Modified                HorseId     OwnerId
----------------------- ----------- -----------
2006-10-20 10:00:00.000 1           1
2006-10-20 10:00:00.000 1           2
2006-10-20 10:00:00.000 1           4
2006-10-20 10:00:00.000 3           1
2006-10-20 10:00:00.000 3           2
2006-11-03 12:00:55.157 2           1
2006-11-03 12:00:55.157 2           2
2006-11-03 12:26:33.733 1           1
2006-11-03 12:26:33.733 1           2
2006-11-03 12:26:33.733 1           4
2006-11-03 12:26:59.327 3           1
2006-11-03 12:26:59.327 3           4
2006-11-03 12:40:45.077 5           1
2006-11-04 00:12:22.280 1           1
2006-11-06 00:00:00.000 1           1
2006-11-09 00:00:00.000 1           1
2006-11-13 00:00:00.000 3           1
2006-11-13 00:00:00.000 3           4
2006-11-13 00:00:00.000 2           1
2006-11-13 00:00:00.000 2           2
2006-11-13 00:00:00.000 5           1
2006-11-13 00:00:00.000 6           NULL
2006-11-14 00:00:00.000 2           1
2006-11-14 00:00:00.000 2           2
2006-11-14 00:00:00.000 2           4
2006-11-17 00:00:00.000 1           1
2006-11-17 00:00:00.000 6           NULL
2006-11-18 00:00:00.000 2           1
2006-11-18 00:00:00.000 2           2
2006-11-18 00:00:00.000 2           4
2006-11-18 00:00:00.000 3           1
2006-11-18 00:00:00.000 3           2
2006-11-21 00:00:00.000 7           NULL
2006-11-21 00:00:00.000 8           NULL
2006-11-22 00:00:00.000 2           1
2006-11-22 00:00:00.000 2           2
2006-11-22 00:00:00.000 2           4
2006-11-30 00:00:00.000 1           2
2006-12-01 00:00:00.000 1           1

(39 row(s) affected)

Het rare is dat deze dus wel NULL geeft. Maar dat komt omdat er helemaal geen record bestaat in dbo.HorseOwner voor dbo.HorseVersion

Of kijk ik ergens enorm overheen?

[ Voor 8% gewijzigd door Slagroom op 30-11-2006 09:29 ]


  • PhysicsRules
  • Registratie: Februari 2002
  • Laatst online: 31-03 07:26

PhysicsRules

Dux: Linux voor Eenden

De specifieke combinatie
code:
1
2006-11-30 00:00:00.000 1           NULL

staat hier ook niet in.

  • Slagroom
  • Registratie: Juni 2001
  • Laatst online: 05-10-2024
Klopt, hij laat alleen een NULL zien als er helemaal geen record in dbo.HorseOwner is ookal is er wel een record in dbo.HorseVersion. Als dat laatste het geval is moet hij toch ook een NULL laten zien?

Is de eerste query:
SQL:
1
2
3
4
5
6
7
SELECT     TOP (100) PERCENT Modified, HorseId, 
                          (SELECT     TOP (1) OwnerId 
                            FROM          dbo.HorseOwner 
                            WHERE      (HorseId = dbo.HorseVersion.HorseId) AND (Modified = dbo.HorseVersion.Modified) AND (OwnerId = 1)) AS OwnerId 
FROM         dbo.HorseVersion 
WHERE     (HorseId = 1) 
ORDER BY Modified

een goede oplossing? Deze doet wel precies wat ik wil maar misschien is het wat performance betreft een drama...

[ Voor 57% gewijzigd door Slagroom op 30-11-2006 11:20 ]


  • PhysicsRules
  • Registratie: Februari 2002
  • Laatst online: 31-03 07:26

PhysicsRules

Dux: Linux voor Eenden

Wat je dan zou kunnen doen is
SQL:
1
2
3
4
SELECT * FROM HorseVersion HV
LEFT JOIN HorseOwner HO
ON HV.HorseID = HO.HorseID AND HV.Modified = HO.Modified AND HO.OwnerID = 1
WHERE HV.HorseID= 1

Dan neem je alle HorseID = 1 regels en houdt die tegen alle OwnerID =1 entries aan.
Dan heb

Edit:
Graag gedaan :)

[ Voor 4% gewijzigd door PhysicsRules op 30-11-2006 12:27 ]


  • Slagroom
  • Registratie: Juni 2001
  • Laatst online: 05-10-2024
Bedankt PhysicsRules!

Deze query:
SQL:
1
2
3
4
5
SELECT [HorseVersion].[Modified], [HorseVersion].[HorseId], [HorseOwner].[OwnerId]
FROM [HorseVersion]
LEFT JOIN [HorseOwner] ON [HorseVersion].[HorseId] = [HorseOwner].[HorseId] AND [HorseVersion].[Modified] = [HorseOwner].[Modified] AND [HorseOwner].[OwnerId] = 1
WHERE [HorseVersion].[HorseId] = 1
ORDER BY [HorseVersion].[Modified]

Geeft dit als resultaat:
code:
1
2
3
4
5
6
7
8
9
10
11
12
Modified                HorseId     OwnerId
----------------------- ----------- -----------
2006-10-20 10:00:00.000 1           1
2006-11-03 12:26:33.733 1           1
2006-11-04 00:12:22.280 1           1
2006-11-06 00:00:00.000 1           1
2006-11-09 00:00:00.000 1           1
2006-11-17 00:00:00.000 1           1
2006-11-30 00:00:00.000 1           NULL
2006-12-01 00:00:00.000 1           1

(8 row(s) affected)

In deze query heb ik meer vertrouwen!
Pagina: 1