在SQL中如何编写查询以从1到多关系返回1条记录?

时间:2010-11-10 20:58:15

标签: sql

假设我有一个Person表和一个具有1对多关系的Purchases表。我想运行一个返回此人的查询,以及他们最近的购买。这似乎很容易,但我似乎无法得到它。

8 个答案:

答案 0 :(得分:3)

假设你有类似于PurchaseDate列的东西,并且想要一个特定的人(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

答案 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

如果您删除WHERE子句,此查询还会显示所有用户的最新购买。

答案 2 :(得分:1)

许多数据库以不同的方式执行“限制或顶部”命令。以下是参考http://troels.arvin.dk/db/rdbms/#select-limit,以下是一些示例

如果使用SQL Server

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

应该适用于MySQL

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

答案 3 :(得分:1)

严格地脱离我的头顶!...如果它只有一个记录那么......

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

...否则

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

我想!我现在还没有访问SQL框来测试它。

答案 4 :(得分:0)

根本不了解您的结构或您的dbms,您可以按购买日期/时间对结果进行排序,并仅返回第一个join ed记录。

答案 5 :(得分:0)

尝试TOP 1按日期的desc订单。例如:

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

答案 6 :(得分:0)

如果您想为每个人选择最新购买,那将是:

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

如果你想让所有人也没有购买,你需要使用LEFT JOIN。

答案 7 :(得分:0)

我认为你还需要一个名为Items的表。 PERSONS表将唯一地定义每个人及其所有属性,而ITEMS表将唯一地定义每个项及其属性。

假设如下:

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

一个人父母可以绑定一个,一个或多个购买孩子。 一个项目父项可以绑定到无,一个或多个购买子项。 一个或多个购买儿童将绑定到一个人父母和一个项目父母。

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

这应该返回:

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