Jointure externe SQL en combinaison avec la fonction MAX dans la table de droite

J'ai une question SQL basée sur la structure de la table ci-dessous. La database est actuellement dans MS Access, avec des plans pour migrer vers SQL Server. La requête devrait fonctionner dans les deux SGBD.

Je veux get devName et la dernière version de dswSW, basée sur dswTimestamp, pour le périphérique en question. Si aucun historique SW n'existe, je veux juste returnner le devName.

Le plus proche que j'ai pu avoir était:

SELECT dev.devname, dsw1.dswsw_version FROM device_sw_history AS dsw1 RIGHT JOIN device AS dev ON dsw1.dswdevid = dev.devid WHERE dsw1.dswtimestamp = (SELECT MAX(dswtimestamp) FROM device_sw_history AS dsw2 WHERE dsw1.dswdevid = dsw2.dswdevid) AND devid = @devid 

Mais rien n'est returnné pour devid = 2, car MAX returnne null. Je veux returnner Apple, null.

Existe-t-il un moyen de build cette instruction sans utiliser UNION et toujours renvoyer devname même si aucun historique SW n'existe?

 Device: devid devname 1 Samsung 2 Apple Device_SW_History: dswid dswdevid dswtimestamp dswsw_version 1 1 5/dec/13 One 2 1 6/dec/13 Two 

Je vous remercie !

Sur SQL Server, une simple sous-requête devrait faire l'affaire:

 SELECT devname, (SELECT TOP 1 dswsw_version FROM device_sw_history WHERE dswdevid = devid ORDER BY dswtimestamp DESC) FROM device 

Cela renverra tous les noms de périphériques du périphérique, même ceux qui n'ont pas d'input dans device_sw_history.

Mettez simplement votre condition dans la clause on:

 SELECT dev.devname, dsw1.dswsw_version FROM device_sw_history AS dsw1 RIGHT JOIN device AS dev ON dsw1.dswdevid = dev.devid AND dsw1.dswtimestamp = (SELECT MAX(dswtimestamp) FROM device_sw_history AS dsw2 WHERE dsw1.dswdevid = dsw2.dswdevid) WHERE devid = @devid 

Pour les jointures internes, les clauses on et where sont identiques, et mettre une condition dans l'une ou dans l'autre est simplement une question de style et de lisibilité. Les jointures externes introduisent une différence entre on et where, la clause on ne s'applique qu'à une table, tandis que la clause where s'applique à leur combinaison.

Actualiser pour mettre la sous-requête à la condition de join l'extérieur est une mauvaise chose. C'est un tueur de performance. Ce que vous pouvez faire est:


/ *
– préparer la structure et datatables
déclare @devid int = 2
select 1 devid, devname 'Samsung' dans #device
insert dans #device values ​​(2, 'Apple')

select 1 dswid, 1 dswdevid, CAST ('05 .12.2013 'comme date) dswtimestamp,' One 'AS dswsw_version dans #Device_SW_History
insert dans les valeurs #Device_SW_History (2,1, CAST ('06 .12.13 'comme date),' Two ') * /

SÉLECTIONNER
dev.devname,
dsw1.dswsw_version
FROM #device_sw_history AS dsw1
DROIT JOIGNEZ #device AS dev
ON dsw1.dswdevid = dev.devid
OERE (dsw1.dswtimestamp = (SELECT MAX (dswtimestamp) FROM #device_sw_history AS dsw2 O d dsw1.dswdevid = dsw2.dswdevid)
OU dsw1.dswtimestamp IS NULL)
ET devid = @devid