2010-04-01 3 views
0

Il existe un tableau des taux de change dans MS SQL Server 2005:
Tâche de requête SQL, décision?

ID | CURR | TARIF | DATE
    | USD       | 30             | 01.10.2010
    | GBP       | 45             | 07.10.2010
    | USD       | 31             | 08.10.2010
    | GBP       | 46             | 09.10.2010
    | USD       | 32             | 12.10.2010
| GBP       | 48             | 03.10.2010

Les taux sont mis à jour en temps réel et il y a plus de 1 milliard de lignes dans le tableau.

Il doit écrire une requête SQL, qui fournira les derniers tarifs pour chaque devise.
Ma décision est:

SELECT c.[id],c.[curr],c.[rate],c.[date]  
FROM [curr_rate] c, (SELECT curr, MAX(date) AS rate_date FROM [curr_rate] 
     GROUP BY curr) t 
WHERE c.date = t.rate_date AND c.curr = t.curr 
ORDER BY c.[curr] ASC 

Est-il possible d'écrire une requête sans sous-requêtes et se joindre à des tables de dérivés?

Répondre

1

Non, je ne pense pas. Avez-vous un index sur CURR et date?

+0

Pour choisir un index primaire pour la table - c'est une tâche secondaire pour cette question. Je pense que PRIMARY INDEX devrait contenir des champs CURR et DATE. –

0

Je ne sais pas que vous pouvez éviter la sous-sélection, mais vous pouvez éviter le rejoindre et même le group by:

SELECT id, curr, rate, date 
FROM curr_rate r 
WHERE date = (
     SELECT MAX(date) 
     FROM curr_rate 
     WHERE curr = r.curr 
    ) 
ORDER BY curr ASC 

Je ne sais pas comment cela se produira.

+0

Cette requête était ma première décision, mais je suppose que ma requête serait meilleure en performance (plus rapide). Qui sait, lequel est le plus perfomance (mieux)? –

+0

Il est extrêmement difficile à dire, @Sirius. Vous devriez toujours tester les requêtes pour les performances. –

1

Le tri de vos index est probablement plus important que la syntaxe SQL pour l'optimisation de cette requête.

Il pourrait être intéressant de comparer l'approche de sous-requête contre un CTE:

;WITH currCTE 
AS 
(
     SELECT id 
       ,curr 
       ,rate 
       ,date 
       ,ROW_NUMBER() OVER (PARTITION BY curr 
            ORDER BY date desc 
           ) AS rn 
     FROM [curr_rate] 
) 
SELECT id 
     ,curr 
     ,rate 
     ,date 
FROM currCTE 
WHERE rn = 1 

Si la table PK est sur id, et les lignes sont toujours ajoutées à la table dans l'ordre chronologique, vous pouvez obtenir de meilleures performances en utilisant id dans la clause ORDER BY de la fonction de classement plutôt que de la date.

+0

c'était juste une question/tâche - pré-entrevue pour le travail. Maintenant, je pense qu'il n'y a pas de décision avec des sous-requêtes et des jointures pour la tâche. –

1

Votre requête n'utilise pas de sous-requête, donc pas besoin de changer cela. Une sous-requête est une requête SELECT qui renvoie une seule valeur et est imbriquée dans une instruction SELECT, INSERT, UPDATE ou DELETE, ou dans une autre sous-requête. Une sous-requête peut être utilisée partout où une expression est autorisée. Voir Subquery Fundamentals

Votre requête utilise une table dérivée, également appelée vue en ligne, que vous avez appelée "t".

Je commencerais en se débarrassant de l'ancienne syntaxe de jointure:

SELECT 
    c.[id],c.[curr],c.[rate],c.[date]  
    FROM [curr_rate] c 
     INNER JOIN (SELECT 
         curr, MAX(date) AS rate_date 
         FROM [curr_rate] 
         GROUP BY curr 
        ) t ON c.curr = t.curr AND c.date = t.rate_date 
    ORDER BY c.[curr] ASC 

mais il aura le même plan d'exécution. Vous pouvez simplement déplacer la table dérivée dans un CTE, mais c'est à peu près la même chose qu'une table dérivée.

La requête serait probablement courir plus vite si vous avez créé une vue indexée sur:

SELECT 
    curr, MAX(date) AS rate_date 
    FROM [curr_rate] 
    GROUP BY curr 

avec un index sur Curr + MAX (date). Si vous auriez alors un index sur [curr_rate] .curr + la date, votre requête aurait de meilleures performances et être:

SELECT 
    c.[id],c.[curr],c.[rate],c.[date]  
    FROM [curr_rate] c 
     INNER JOIN [curr_rate_max_view] t ON c.curr = t.curr AND c.date = t.rate_date 
    ORDER BY c.[curr] ASC