2011-06-29 5 views
0

Est-ce que quelqu'un peut me diriger vers un exemple de CTE utilisé pour parcourir un jeu d'enregistrements au lieu d'un curseur?CTE au lieu du curseur

Tous les exemples que j'ai pu trouver montrent une récursivité. Je n'ai pas besoin de ça. Je veux juste parcourir un jeu d'enregistrements un à la fois.

Merci.

(EDIT)

Peut-être est mieux demandé une autre façon. J'ai supposé qu'un CTE ou un curseur pourrait être le meilleur moyen d'obtenir les données que je veux, mais voici un exemple.

Si j'ai une table avec des ID utilisateur, des codes et des dates comme suit, où l'ID utilisateur n'est pas une clé primaire.

 
2011-05-24 11:06:28.080  CODE1 199 
2011-05-24 11:06:28.080  CODE2 199 
2011-06-08 13:30:14.830  CODE2 209 
2011-06-08 13:30:14.313  CODE1 209 
2011-06-08 13:30:13.840  CODE2 209 
2011-06-08 13:30:13.450  CODE1 209 
2011-06-08 13:30:13.050  CODE2 209 
2010-05-07 10:45:06.800  CODE3 79 
2010-05-07 10:45:04.833  CODE3 79 
2010-10-15 07:30:16.193  CODE3 79 
2010-01-26 13:51:43.923  CODE3 79 
2010-01-26 13:51:43.923  CODE3 79 
2010-01-26 13:51:44.427  CODE3 79 
2010-01-26 13:51:45.103  CODE3 79 
2010-01-26 13:51:45.890  CODE3 79 
2010-01-26 13:51:46.733  CODE3 79 
2010-01-25 12:40:39.737  CODE3 81 
2010-01-25 12:40:40.890  CODE3 81 
2010-01-25 12:40:41.627  CODE3 81 
2010-01-25 12:40:43.277  CODE3 81 
2010-01-25 14:29:08.360  CODE3 81 
2010-01-21 19:36:34.660  CODE3 98 
2010-01-21 19:36:34.843  CODE3 98 
2010-01-21 19:36:35.013  CODE3 98 
2010-01-21 22:27:24.317  CODE3 83 
2010-01-21 22:31:21.443  CODE2 83 
2010-01-22 19:44:28.880  CODE3 83 

Et je veux choisir à partir de ce tableau la plus ancienne date et le code pour chaque utilisateur est-il possible de le faire en utilisant un CTE?

je peux faire une sélection où je groupe par customerid et obtenir le MIN (datefield) mais je reçois ne peut pas récupérer le code associé à cette date au plus tôt à moins que je l'ajouter à mon groupe par article ... puis de Bien sûr, je reçois plusieurs lignes pour un client, une avec chaque code associé.

J'ai trouvé une solution qui fonctionne lorsque je crée une table temporaire et que je la remplis avec le MIN (Date) et l'ID client en les regroupant sur le clientid. Ensuite, je mets à jour cette table temporaire en la joignant à la table d'origine par le client et le champ date pour obtenir le code associé à cette ligne ... mais cela semble être un hack. Je me demandais si boucler la table d'origine (triée par customerid et date) et chaque fois que je vois un nouvel identifiant client insérant cet enregistrement dans une table temporaire, serait une solution plus propre ... d'autant plus que la solution I La découverte suppose une combinaison unique datetime/customerid.

Voici un exemple de ce que j'utilise maintenant. Il semble juste comme un hack et je me demande si un cusor (que j'évite normalement) ou un CTE serait une solution plus propre.

DECLARE @Table1 TABLE 
(
    ClaimDate datetime, 
    VenueCode nvarchar(50), 
    CustomerID int 
) 
INSERT INTO @Table1 
    SELECT sc.CreateDate, v.code, sc.CSFCustomerID 
    FROM foo join foo1 on (snip) 


DECLARE @Table2 TABLE 
    ( 
    ClaimDate datetime, 
    VenueCode nvarchar(50), 
    CustomerID int) 



INSERT INTO @Table2 
    select MIN(ClaimDate), NULL, CustomerID from @Table1 group by CustomerID 

    UPDATE ft 
    SET ft.SomeCode = t.VenueCode 
FROM @Table2 ft 
INNER JOIN @Table1 t ON ft.CustomerID = t.CustomerID 
AND ft.ClaimDate = t.ClaimDate 

Merci, et je promets que je ferai mieux de choisir les réponses dans le futur.

+1

Les CTE ne remplacent pas les curseurs. Ils sont plus un remplacement pour les tables temporaires. Si vous devez, par exemple, exécuter un code spécifique à chaque itération, un CTE ne vous sera d'aucune aide. –

+3

Pourquoi avez-vous besoin de "franchir" un à la fois? Pourquoi pensez-vous que tout type d'opération rangée par rangée (qu'il s'agisse de DECLARE CURSOR ou non) va fonctionner différemment d'un curseur? Ce qui le ralentit, c'est la partie rangée par rangée, pas la partie DECLARE CURSOR. –

+1

Oui, veuillez expliquer votre cas d'utilisation et nous pouvons vous orienter vers une solution. – JNK

Répondre

0
with qry 
(
SELECT Min(Date), userID 
FROM TABLE 
GROUP BY UserID 
) 

SELECT Table.* 
FROM TABLE 
INNER JOIN qry on qry.UserID = Table.UserID AND qry.Date = Table.Date 
+0

Votre solution ne fonctionne pas une fois que vous avez ajouté le champ VenueCode, Mitch. Merci quand même. – BillyPilgrim

+0

Qu'en est-il ne fonctionne pas? La ligne 'SELECT Table. *' Devrait retourner toutes les colonnes de cette table, y compris la colonne Code ... – therealmitchconnors

0

Bien qu'il soit assez vieux poste et le titre de la question ne convient pas pour illustrer votre tâche principale, qui est finalement: Et je veux choisir à partir de ce tableau pour chaque utilisateur la plus ancienne date et le code est-il possible pour ce faire en utilisant un CTE?

La réponse est oui. Vous pouvez essayer ceci:

-- CTE version of the SQL 
WITH CTE (OldestClaimData, CustomerID) 
AS 
(
    SELECT 
    MIN(ClaimDate), CustomerID 
    FROM 
    UserClaims 
    GROUP BY 
    CustomerID 
) 
SELECT DISTINCT 
    UC.* 
FROM 
    UserClaims UC 
INNER JOIN 
    CTE ON (
    CTE.OldestClaimData=UC.ClaimDate 
    AND 
    CTE.CustomerID=UC.CustomerID 
    AND 
    UC.VenueCode=(
     SELECT TOP 1 
     VenueCode 
     FROM 
     UserClaims sub 
     WHERE 
     sub.ClaimDate=UC.ClaimDate 
     AND 
     sub.CustomerID=UC.CustomerID 
    ) 
) 
ORDER BY 
    UC.CustomerID; 

J'ai mis mon code et le vôtre dans un SQL Fiddle pour votre commodité.

P.D.: travaillez sur votre accept rate.

Questions connexes