2013-03-26 4 views
3

Nous avons cette table, où les actions des joueurs sont enregistrées. Je voudrais savoir où les gens achètent leur équipement (Item Bow ou Sword). L'équipement peut être acheté dans la boutique ou aux enchères (l'endroit peut être trouvé dans la colonne Action). Ainsi, lorsque le joueur achète un article, nous devons trouver Action Shop ou aux enchères (dépend de l'un d'entre eux est survenue la dernière avant qu'un article a été acheté)Trouver les enregistrements précédents après les avoir spécifiés et les joindre

**User  Time  Action   Item** 
    1   12:00  Auction 
    2   12:01  Shop 
    3   12:04  Shop 
    4   12:09  Shop   
    4   12:15  Buy    Bow 
    2   12:15  Auction 
    2   12:19  Auction 
    1   12:25  Chat  
    4   12:33  Auction   
    3   12:47  Chat 
    1   12:47  Buy    Sword 
    2   12:47  Buy    Bow 
    3   12:50  Buy    Sword 
    4   12:52  Buy    Bow 
    3   12:56  Buy    Bow 

Le resulut devrait être

**Time  Item   Place** 
12:15  Bow   Shop 
12:47  Sword  Auction 
12:47  Bow   Auction 
12:50  Sword  Shop 
12:52  Bow   Auction 
12:56  Bow   Shop 

I pense que je pourrais avoir une idée de comment le résoudre avec cross appliquer en mssql, mais est-il possible de le résoudre sans elle? Je pourrais aussi utiliser la requête dans ruche. Je serais reconnaissant pour toute réponse. Je vous remercie!

+0

Quelle saveur de SQL Server utilisez-vous? Si vous utilisez 2008, vous pouvez utiliser une "expression de table commune" et, si vous incluez le "ROW_NUMBER()", vous pouvez joindre le CTE à lui-même sur "b.row_num_alias = a.row_num_alias-1' –

+0

@ DuncanHowe qui travaillerait jusqu'en 2005 aussi. –

+0

@Aaron - En effet - mais j'ai vu des problèmes de performance en utilisant des CTE en 2005, qui ne se sont pas manifestés en 2008. Pour 2005, je préfère utiliser des tables temporaires. –

Répondre

1

Vous voudrez peut-être quelque chose comme ça (et je devine que vous pourriez aimer l'utilisateur là-dedans aussi, hein?)

RÉPONSE MIS À JOUR grâce à la suggestion de Tim

with p as -- pick purchases 
(SELECT [user], [time] purchased, [item] 
    FROM actions 
    WHERE [action] = 'Buy' 
), e as  -- pick entrances where something can be bought 
(SELECT [user], [time] entered, [action] place 
    FROM actions 
    WHERE [action] IN ('Auction', 'Shop') 
), j as  -- join purchases with all prior entrances 
(SELECT p.[user], p.[purchased], p.[item], 
     e.[entered], e.[place] 
    FROM p 
    JOIN e on p.[user]=e.[user] 
      and p.[purchased]>=e.[entered] 
), r as  -- rank entrance closeness to purchase 
(SELECT *, row_number() over(partition by [user],[purchased],[item] 
           order by [entered] desc) as rnk 
    FROM j 
)   -- select only where entrance is the closest 
SELECT [user],[purchased],[item],[place] 
    FROM r 
    WHERE rnk = 1 
    order by [user],[purchased],[item] 

caveat: TSQL est pas mon dialecte natif ;-)

+1

Essayez votre requête: http://www.sqlfiddle.com/#!3/eb27f/11/0 –

+0

Merci Tim, très cool. J'ai réécrit ma réponse entièrement :-) – WarrenT

+0

Cela a été extrêmement utile. Merci et Tim aussi :) – Gorionovic

0

Essayez:

select time, item, (
    select top 1 Actions.action 
    from Actions 
    where Actions.[User] = buy.[user] and 
     Actions.action in ('shop', 'auction') and 
     Actions.time < buy.time 
    order by Actions.time desc 
        ) 
from Actions as buy 
where action = 'buy' 

testé grâce à sqlfiddle fourni par Tim Schmelter (excellent outil, je ne savais pas à propos de !!)

+0

cela fonctionne pour moi comme prévu –

Questions connexes