10
votes

SQL rejoindre uniquement le puzzle de ligne maximum

Compte tenu des données suivantes:

+--------------------+------------+-----------+----------------+---------------+-------------+
| Network Identifier | First Name | Last Name | Hardware Name  | Serial Number | Assigned On |
+--------------------------------------------------------------------------------------------+
| bro4               | Billy      | O'Neal    | Latitude E6200 | 2222222       | April 10    |
+--------------------+------------+-----------+----------------+---------------+-------------+
| jsk1               | John       | Skeet     | Latitude E6500 | 5555555       | April 11    |
+--------------------+------------+-----------+----------------+---------------+-------------+


2 commentaires

Alors tu as le vieil ordinateur portable de Jon Skeet? Kewl!


@APC: Oui! La société a pensé qu'il dépendait trop de temps sur Stackoverflow ... :)


3 Réponses :


8
votes
select * from Users as u
inner join HardwareAssignments as ha
    on u.id = ha.userid
inner join Hardware as h
    on uh.hardwareid = h.id
where ha.AssignedOn = (select max(assignedon)
                       from HardwareAssignments as ha2
                       where ha.userid = ha2.userid)
That could get you close. Not sure if it's exact.

2 commentaires

Ajustez les colonnes à vos besoins, mais la partie clé de la solution est la sous-requête.


Doh! * Bill se sent un peu bête maintenant



0
votes

Utiliser le groupe par et max pour filtrer les résultats de la jointure.


1 commentaires

Cela ne renvoie qu'une rangée. J'ai besoin d'une ligne par utilisateur.



9
votes
SELECT U.NetworkIdentifier, U.FirstName, U.LastName,
       H.HardwareName, H.SerialNumber
  FROM (SELECT UserID, MAX(AssignedOn) LastAssignment
          FROM HardwareAssignments
         GROUP BY UserID) AS T
  JOIN HardwareAssignments AS HA
       ON HA.UserId = T.UserID AND HA.AssignedOn = T.LastAssignment
  JOIN Users AS U ON U.ID = HA.UserID
  JOIN Hardware AS H ON H.ID = HA.HardwareID
 ORDER BY U.NetworkIdentifier;
The difference between this and Justin Niessner's answer is where the sub-query appears; here, I've created it in the FROM clause.  This pretty much guarantees that it is executed once.  When there's a correlated sub-query in the WHERE clause as in Justin's answer, it is possible that the optimizer will execute the sub-query once for each row - which is more expensive when the tables are big.  A really good optimizer might flatten things so that the two are equivalent.

4 commentaires

+1 Si l'OP est capable de faire fonctionner cette version, elle fonctionnera beaucoup mieux que mon message (pour les grands ensembles de données ... et aussi longtemps que l'optimiseur de requête n'a pas aplati que ma requête ne fonctionne de cette manière).


@Justing Niessner: déplacé la réponse acceptée à celle-ci sur la base du commentaire ci-dessus. S'il vous plaît ne le prenez pas personnellement :)


+1 Testé cela brièvement, un gain énorme. Cependant, il convient de noter que la requête corrélée peut mieux fonctionner si la requête extérieure a une sélectivité élevée et des tables sont énormes (bien qu'il soit facile d'améliorer la requête ci-dessus en répétant les critères de sélection sur la requête interne).


@UnReason: il n'y a pas de critères de sélection sur la requête extérieure. (Ceci est pour une fonction export-to-csv)