【问题标题】:T-SQL Select join with conditionT-SQL 选择有条件的连接
【发布时间】:2013-03-16 08:45:53
【问题描述】:

假设我有 3 张桌子:

  1. 汽车

    • 身份证
  2. CarColorHistory

    • 身份证
    • 汽车ID
    • 颜色ID
    • 修改日期
  3. 颜色

    • 身份证
    • 颜色名称

我想选择所有汽车及其颜色,但重要的是,汽车的颜色是 CarColorHistory 表中最后修改的颜色。

我需要使用 join 来执行此操作。

例子:

汽车:

1
2

汽车颜色历史:

1 1 1 26/03/2012  -> (actual color, can be take by date or id)
2 1 2 25/03/2012
3 2 2 25/03/2012

颜色:

1 Blue
2 Red

我需要得到结果:(car id, colorName)

1 Blue
2 Red

我尝试通过加入 Cars 表和 CarColorHistory 表来实现它,但我得到了所有颜色的汽车。我只需要实际颜色(最后添加)。

请帮忙

【问题讨论】:

  • 评论。为什么需要颜色历史的 ID?

标签: sql-server tsql join max


【解决方案1】:

试试这个:

select c.id, colorname
from cars c
inner join CarColorHistory h on c.id = h.CarID
inner join Color c2 on h.colorid = c2.id
where h.ModificationDate = (select max(ModificationDate)
                            from CarColorHistory x where c.id = x.CarId)

【讨论】:

  • 谢谢,这正是我需要的:*
【解决方案2】:

您可以通过多种方式获得结果。您可以使用子查询来获取max(modificationdate)

select c.id, r.colorname
from cars c
inner join CarColorhistory h1
  on c.id = h1.carid
inner join
(
  select max(modificationdate) MaxDate,
    carid
  from CarColorhistory
  group by carid
) h2
  on h1.carid = h2.carid
  and h1.modificationdate = h2.maxdate
inner join color r
  on h1.colorid = r.id

SQL Fiddle with Demo

或者由于您使用的是 SQL Server,您可以使用ranking functions

select id, colorname
from
(
  select c.id, r.colorname,
    row_number() over(partition by c.id order by modificationdate desc) rn
  from cars c
  inner join CarColorhistory h1
    on c.id = h1.carid
  inner join color r
    on h1.colorid = r.id
) src
where rn = 1;

SQL Fiddle with Demo

【讨论】:

    【解决方案3】:

    这应该对你有用:

    SELECT c.id, (
        SELECT co.ColorName FROM Color co
        WHERE co.id = (
            SELECT TOP 1 ColorID FROM CarColorHistory
            WHERE CarID = c.id
            ORDER BY ModificationDate DESC
        )
     ) AS ColorName
    

    【讨论】:

    • 谢谢,但您能通过 JOIN ON 语句帮助我做到这一点吗?我怎样才能在 JOIN 中使用你的粗体?这对我的老师很重要。
    【解决方案4】:

    这样做的一种方法可能是只使用子查询,就像之前发布的那样,因为您使用的是 t-sql,所以您也应该能够通过应用来做到这一点:

    SELECT
            Cars.Id, LatestColors.ColorID, LatestColors.ModificationDate
        FROM Cars
        CROSS APPLY (
            SELECT TOP 1
                    ColorID, ModificationDate
                FROM CarColorHistory
                WHERE CarID = Cars.ID
                ORDER BY ModificationDate DESC
        ) AS LatestColors
    

    【讨论】:

      【解决方案5】:

      如果你有Sql Server 2005 或更高版本,你可以试试这个:

      你可以在这里试试,Common table expression 是如何工作的:Sql Fiddle demo

        ;WITH CTE_Cars(CarID, MaxDate)
          AS
          (
          SELECT CarID, MAX(ModificataionDate) AS MaxDate
          FROM CarColorHistory
          GROUP BY CarID
          )
          SELECT CTE_Cars.CarID, Color.ColorName
          FROM 
          CTE_Cars
          INNER JOIN CarColorHistory ON CarColorHistory.CarID = CTE_Cars.CarID AND
          CarColorHistory.ModificataionDate = CTE_Cars.MaxDate
          INNER JOIN Color ON Color.id = CarColorHistory.ColorId
      

      【讨论】:

        【解决方案6】:

        我不确定这是否是最好的方法,但我就是这样做的。首先使用 MAX 从表格中获取您想要的值,然后将该结果用作JOIN 的表格,以消除不需要的值。

        SELECT c.ID, Color.Color
        From Cars c JOIN CarColorHistory h on c.id = h.CarID
             JOIN Color on h.ColorID = Color.ID
             JOIN
        
            --Create a table with only the latest value and the car ID
            ( 
            SELECT c.ID, Max(h.TimeStamp) as time
            FROM Cars c JOIN CarColorHistory h on c.id = h.CarID
                 JOIN Color on h.ColorID = Color.ID
            Group by c.ID --Join the table on latest time to get rid of old timestamps
            ) Max on Max.ID = c.ID and h.TimeStamp=max.time
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-09-18
          • 2014-11-25
          • 1970-01-01
          • 2018-08-15
          • 2014-04-08
          • 2017-06-05
          • 2010-12-23
          相关资源
          最近更新 更多