2010-11-10 4 views
1

Disons que j'ai une table Person et une table Achats avec une relation de 1 à plusieurs. Je veux lancer une seule requête qui renvoie cette personne et juste leur dernier achat. Cela semble facile mais je n'arrive pas à l'obtenir.En SQL, comment écrire une requête pour retourner 1 enregistrement d'une relation 1 à plusieurs?

+0

Je crois que nous avons besoin de plus d'informations sur vos tables.La personne est-elle la clé de chaque table? Comment stockez-vous vos achats dans la table d'achat? – prolink007

+0

Qu'est-ce qui détermine quel achat est le plus récent - une colonne date/heure peut-être? Et pour quelle base de données? –

Répondre

3

En supposant que vous avez quelque chose comme une colonne de purchaseDate et que vous voulez une personne en particulier (SQL Server):

SELECT TOP 1 P.Name, P.PersonID, C.PurchaseDescription FROM Persons AS P 
INNER JOIN Purchases AS C ON C.PersonID = P.PersonID 
WHERE P.PersonID = @PersonID 
ORDER BY C.PurchaseDate DESC 
+0

+1 Cela fonctionne pour T-SQL; D'autres DMBS en plus de MSSQL auront un équivalent différent pour 'TOP' qui fera aussi la même chose. –

0

Sans connaître la structure du tout, ou votre DBMS, vous trier les résultats en ordre décroissant, la date d'achat/heure et renvoie uniquement le premier enregistrement join.

1

De nombreuses bases de données préforment la commande "Limit or Top" de différentes manières. Voici une référence http://troels.arvin.dk/db/rdbms/#select-limit et ci-dessous sont quelques échantillons

Si vous utilisez SQL Server

SELECT TOP 1 
    * 
FROM Person p 
INNER JOIN Purchases pc on pc.PersonID = P.PersonID 
Order BY pc.PurchaseDate DESC 

devrait fonctionner sur MySQL

SELECT 
    * 
FROM Person p 
INNER JOIN Purchases pc on pc.PersonID = P.PersonID 
Order BY pc.PurchaseDate DESC 
LIMIT 1 
3
select p.*, pp.* 
from Person p 
left outer join (
    select PersonID, max(PurchaseDate) as MaxPurchaseDate 
    from Purchase 
    group by PersonID 
) ppm 
left outer join Purchase pp on ppm.PersonID = pp.PersonID 
    and ppm.MaxPurchaseDate = pp.PurchaseDate 
where p.PersonID = 42 

Cette requête affiche également le dernier achat pour tous utilisateurs si vous supprimez la clause WHERE.

+0

Ouais! La première réponse où un "group by" et une table dérivée (ou inline view) sont utilisés. – Rawheiser

+0

+1 Portable et fonctionne bien sur SQL Server. – onedaywhen

0

Essayez TOP 1 Avec une commande par tirage le. Ex:

CREATE TABLE #One 
(
    id int 
) 

CREATE TABLE #Many 
(
    id int, 
    [date] date, 
    value int 
) 

INSERT INTO #One (id) 
SELECT 1 UNION ALL 
SELECT 2 UNION ALL 
SELECT 3 

INSERT INTO #Many (id, [date], value) 
SELECT 1, GETDATE(), 1 UNION ALL 
SELECT 1, DATEADD(DD, 1 ,GETDATE()), 3 UNION ALL 
SELECT 1, DATEADD(DD, -1 ,GETDATE()), 0 

SELECT TOP 1 * 
    FROM #One O 
    JOIN #Many M ON O.id = M.id 
    ORDER BY [date] DESC 
0

Si vous voulez sélectionner le dernier achat pour chaque personne, ce serait:

SELECT PE.ID, PE.Name, MAx(PU.pucrhaseDate) FROM Persons AS PE JOIN PURCHASE as PU ON PE.ID = PU.Person_ID 

Si vous voulez avoir toutes les personnes aussi ceux qui ont pas d'achat, vous devez utiliser JOINT GAUCHE.

1

strictement du haut de ma tête! ... Si c'est seulement un enregistrement alors ...

SELECT TOP 1 * 
FROM Person p 
    INNER JOIN Purchases pu 
    ON p.ID = p.PersonId 
ORDER BY pu.OrderDate 
WHERE p.ID = *thePersonYouWant* 

autrement ...

SELECT TOP 1 * 
FROM Person p 
INNER JOIN 
(
SELECT TOP 1 pu.ID 
    FROM Purchases pu 
     ON pu.PersonID = p.Id 
ORDER BY pu.OrderDate 
) sq 

Je pense! Je n'ai pas encore accès à une boîte SQL pour le tester.

0

Je pense que vous avez besoin d'une autre table appelée Items par exemple. La table PERSONNES définirait de manière unique chaque personne et tous ses attributs, tandis que la table ITEMS définirait de façon unique chaque élément et leurs attributs.

On suppose les éléments suivants:

Persons   |Purchases     |Items 
PerID PerName |PurID PurDt PerID ItemID |ItemID ItemDesc ICost 
101 Joe Smith |201 101107 101 301 |301 Laptop 500 
       |202 101107 101 302 |302 Desktop 699 
102 Jane Doe |203 101108 102 303 |303 iPod  199 
103 Jason Tut |204 101109 101 304 |304 iPad  499 
       |205 101109 101 305 |305 Printer 99 

Une seule personne parent peut attacher à aucun, un ou plusieurs enfants d'achat. Un élément Parent peut être nul, un ou plusieurs enfants. Un ou plusieurs achats Les enfants seront liés à un parent et un parent.

select per.PerName as Name 
    , pur.PurDt  as Date 
    , itm.ItemDesc as Item 
    , itm.ICost  as Cost 
    from Persons per 
    , Purchases pur 
    , Items  itm 
where pur.PerID = per.PerID   -- For that Person 
    and pur.ItemID = itm.ItemID   -- and that Item 
    and pur.PurDt =     -- and the purchase date is 
    (Select max(lst.PurDt)   -- the last date 
     from Purchases lst   -- purchases 
     where lst.PerID = per.PerID) -- for that person 

Cela devrait retourner:

Name   Date Item Cost 
Joe Smith 101109 Ipad  499 
Joe Smith 101109 Printer 99 
Jane Doe  101108 iPod  199 
Questions connexes