【问题标题】:SQL Query return latest date with additional information from tablesSQL 查询返回最新日期以及表中的附加信息
【发布时间】:2014-05-05 20:54:06
【问题描述】:

我有 5 个与此查询相关的表和列:

  • 狗(ID、CallName、颜色、性别、Chipnumber、BreedID)
  • 品种(ID、名称)
  • 状态(ID、状态、OwnedOnPremises)
  • DogsStatus(ID、DogsID、StatusID、StatusDate、Note、ContactsID)
  • 联系人(ID、姓名)

我想要所有狗及其最新状态的结果。对于测试,我使用以下记录:

  • 狗 (251, Tank, Fawn, M, 14410784, 23) (266, Bonnie, Brindle, 14964070, 23)
  • 品种(23,獒)
  • 状态(3,已售出)(4,赠送)(7,已购买)(9,退回)
  • DogsStatus (29, 251, 3, 2013-10-12, 5) (39, 251, 9, 2013-11-10, 17) (146, 251, 4, 2014-01-10, 7) ( 40, 266, 7, 2013-10-30, 1)
  • 联系人 (1, Person1) (5, Person5) (7, Person7) (17, Person17)

到目前为止,我有:

SELECT 
    d.CallName, b.Name AS 'Breed', d.Color, d.Sex, d.ChipNumber
FROM 
    Dogs d
JOIN 
   (SELECT 
        DogsID, MAX(StatusDate) as MaxStatusDate 
    FROM DogsStatus 
    GROUP BY DogsID) mds ON mds.DogsID = d.ID
JOIN 
   Breeds b ON b.ID = d.BreedID

这将返回 2 条唯一记录(1 条用于 Tank,1 条用于 Bonnie),但每当我尝试获取任何其他 DogsStatus 和/或状态信息时,我要么只返回一条狗记录,要么返回全部 3 条 Tanks DogsStatus记录。

提前致谢。

【问题讨论】:

  • 您必须将派生表中的MaxStatusDate 连接到DogsStatus 表。这使您可以将其实际限制为最新状态。
  • SQL Server 2012 速成版

标签: sql sql-server


【解决方案1】:

您需要将您的MaxStatusDate 加入DogsStatus 表。这样,在您有多个状态的情况下,您只会获得最新的状态。 类似的东西

SELECT 
    d.CallName, b.Name AS 'Breed', d.Color, d.Sex, d.ChipNumber
FROM 
    Dogs d
innner join DogsStatus ds
  ON d.dogsid = ds.dogs_id
JOIN 
   (SELECT 
        DogsID, MAX(StatusDate) as MaxStatusDate 
    FROM DogsStatus 
    GROUP BY DogsID) mds ON mds.DogsID = d.ID
JOIN 
   Breeds b ON b.ID = d.BreedID
   AND mds.maxstatusdate = ds.statusdate

类似的东西。

【讨论】:

  • 我缺少的是“AND”语句。作为旁注,我实际上早先尝试过,但由于 Bonnie 的 StatusDate 列是 NULL 并且没有显示为查询的结果,因此我认为我的查询错误地只显示了一条记录,因此得到了倾斜的结果。感谢您的快速回复!
【解决方案2】:

你已经接近了。您只需要返回 DogStatus 表即可获得该完整记录。请注意,我更喜欢 CTE,但您现有的派生表(子查询)方法也可以正常工作:

With StatusDates As
(

    SELECT 
        DogsID, MAX(StatusDate) as StatusDate 
    FROM DogsStatus 
    GROUP BY DogsID
), CurrentStatus As 
(
    SELECT ds.*
    FROM DogStatus ds
    INNER JOIN StatusDates sd ON sd.DogsID = ds.DogsID AND ds.StatusDate = sd.StatusDate
)
SELECT d.Name, b.Name As Breed, d.Color, d.Sex, d.ChipNumber
    , s.Status, cs.StatusDate, c.Name As ContactName
FROM Dogs d
INNER JOIN CurrentStatus cs ON cs.DogsID = d.ID
INNER JOIN Breed b on b.ID = d.BreedID
INNER JOIN Status s on s.ID = cs.StatusID
INNER JOIN Contact c on c.ID = cs.ContactID

您可能希望对其中一些使用 LEFT 联接,然后更改选择列表以使用 coalesce() 表达式来清理 NULL。

【讨论】:

  • 感谢您非常详细的解释和快速响应。这和下面的答案一样有效,但下面的答案对我来说似乎有点简单。我会记住 CTE 的评论。谢谢!
【解决方案3】:

应该是这样的,我相信您可以根据自己的需要进行调整:

;with x as (
  select *, row_number() over(partition by d.DogsId order by StatusDate desc) as rn
  from Dogs d
  inner join DogsStatus on d.DogsId = ds.DogsId
)
select *
from x
where rn = 1

【讨论】:

    猜你喜欢
    • 2014-11-03
    • 2015-04-04
    • 1970-01-01
    • 2013-09-11
    • 2019-05-28
    • 2012-01-26
    • 1970-01-01
    • 2020-07-04
    • 2014-05-23
    相关资源
    最近更新 更多