2009-04-11 9 views
0

j'ai une table appelée tblAssetsInUse avec la structure suivante:SQL Trouver la date la plus récente de 2 colonnes, et d'identifier quelle colonne il était

intPK  intAssetID  datCheckedOut  datCheckedIn 
1   450    1/5/2009   10/5/2009 
2   300    2/5/2009   <NULL> 
3   200    2/5/2009   <NULL> 
4   450    12/5/2009   5/7/2009 

et j'ai un SP qui reçoit un code d'actif numérisé puis soit Insère ou Mises à jour de la table pour les actifs en cours de vérification Out ou In respectivement. Comme vous pouvez le voir, datCheckedIn peut être Null, ce qui permet de déterminer quels actifs sont actuellement utilisés. Cette procédure fonctionne parfaitement. Je souhaite être en mesure de déterminer quel était le dernier actif à numériser et également quelle était la dernière opération à la table (c.-à-d. Entrée ou Sortie). J'ai un code SQL qui trouve la ligne avec la date la plus récente (indépendamment de la colonne) et je l'utilise ensuite pour rejoindre une vue distincte des actifs, qui fonctionne également. Je dois juste être en mesure de travailler si la date la plus récente était dans la colonne Checked Out ou Checked In en quelque sorte.

SELECT TOP (1) allDates.intPK, MAX(allDates.datLastAction) AS datLastScan, dbo.viwAssets.strFriendlyName, tblAssetsInUse_join.intAssetID 
FROM (SELECT intPK, MAX(datCheckedOut) AS datLastAction 
     FROM dbo.tblAssetsInUse AS tblAssetsInUse_out 
     GROUP BY intPK 

     UNION ALL 

     SELECT intPK, MAX(datCheckedIn) AS datLastAction 
     FROM dbo.tblAssetsInUse AS tblAssetsInUse_in 
     GROUP BY intPK) AS allDates 
INNER JOIN 
dbo.tblAssetsInUse AS tblAssetsInUse_join ON allDates.intPK = tblAssetsInUse_join.intPK 
INNER JOIN 
dbo.viwAssets ON tblAssetsInUse_join.intAssetID = dbo.viwAssets.intPK 
GROUP BY allDates.intPK, dbo.viwAssets.strFriendlyName, tblAssetsInUse_join.intAssetID 
ORDER BY datLastScan DESC 

Y a-t-il une valeur littérale de quelque sorte que je puisse ajouter afin de marquer une valeur de bit dans les résultats peut-être?

Merci pour votre aide,

Paul Reynolds

Répondre

0

A côté d'obtenir le type d'opération effectuée, je pense que toute la requête pourrait être simplifiée (et optimisé) ainsi:

SELECT TOP 1 allDates.intPK, allDates.datLastAction AS datLastScan, allDates.operation, dbo.viwAssets.strFriendlyName, tblAssetsInUse_join.intAssetID 
FROM (SELECT TOP 1 intPK, intAssetID, datCheckedOut AS datLastAction, 'Out' AS operation 
    FROM dbo.tblAssetsInUse AS tblAssetsInUse_out 
    ORDER BY datCheckedOut DESC 

    UNION ALL 

    SELECT TOP 1 intPK, intAssetID, datCheckedIn AS datLastAction, 'In' AS operation 
    FROM dbo.tblAssetsInUse AS tblAssetsInUse_in 
    ORDER BY datCheckedIn DESC) AS allDates 
INNER JOIN 
    dbo.viwAssets ON allDates.intAssetID = dbo.viwAssets.intPK 
ORDER BY datLastScan DESC 

EDIT: Notez également que, en supprimant le TOP 1 dans la première ligne vous obtenez à la fois le dernier actif enregistré et le dernier extrait.

+0

Nice! Je pense que je vais faire cette optimisation. Cela ressemble à une très bonne idée. Ensuite, je serais en mesure de vérifier simplement l'opération pour déterminer laquelle était dans le code. Je vous remercie! –

0

Un moyen serait d'utiliser une instruction CASE et SELECT soit IN ou OUT selon que la valeur de date MAX est IN ou OUT

1

Essayez ceci comme requête intérieure:

SELECT intPK, 'Out', MAX(datCheckedOut) 
FROM dbo.tblAssetsInUse 
GROUP BY intPK 

UNION 

SELECT intPK, 'In', MAX(datCheckedIn) 
FROM dbo.tblAssetsInUse 
GROUP BY intPK 

Edité pour ajouter: Une solution plus lisse serait de créer une fonction définie par l'utilisateur qui compare deux dates.

+0

Cela pourrait être un meilleur moyen - Bon appel –

+0

J'aime ça! Fonctionne un régal. À la vôtre Jamie. Je devais ajouter un alias mais ensuite l'ajouter à la sélection externe et aussi au groupe par. Est-ce que ça sonne bien? –

+0

Oui, ça sonne bien. –

0

Cela devrait fonctionner. Si vous vous retrouvez avec deux éléments enregistrés ou retirés à des moments identiques, vous obtiendrez bien sûr plusieurs lignes.

SELECT 
    intPK, 
    intAssetID, 
    datCheckedOut, 
    datCheckedIn, 
    CASE 
      WHEN datCheckedIn IS NOT NULL THEN 'Checked In' 
      ELSE 'Checked Out' 
    END AS last_action 
FROM 
    tblAssetsInUse AIU 
INNER JOIN 
    (
      SELECT 
       MAX(datCheckedOut) AS max_in, 
       MAX(datCheckedIn) AS max_out 
      FROM 
       tblAssetsInUse 
    ) SQ ON 
    CASE 
      WHEN max_in > max_out THEN max_in 
      ELSE NULL 
    END = AIU.datCheckedIn OR 
    CASE 
      WHEN max_out > max_in THEN max_out 
      ELSE NULL 
    END = AIU.datCheckedOut 
Questions connexes