如何仅返回左连接中表的最大行

时间:2015-01-09 16:05:31

标签: sql sql-server sql-server-2012

我有一张表格,其中包含有关汽车dbo.Car

的信息
CarID | Make      | Model
23      Volvo       XC90
40      Chevrolet   Camaro
46      BMW         Z4   

还有另一个表dbo.CIS,其中列出了其他信息。它是这样的:

CarID | Dist | U1 | U2 | U3 | U4 | U5 -- U22
23      180    65   94   80   56   88    71
23      1170   68   93   24   23   19    93
40      908    89   15   68   46   59    31
46      500    10   20   30   40   50    35
46      2300   60   62   44   52   75    99

这个数据在这个表中意味着什么并不重要。但是我希望加入CarID并且当CarID在该表中出现多次时,只返回Dist表中dbo.CIS列中值最高的1行。

所以对于CarID 23,我想回复一下:

CarID | Make   | Model | CarID | Dist | U1 | U2 | U3 | U4 | U5 -- U22
23      Volvo    XC90    23      1170   68   93   24   23   19    93

到目前为止,我已经尝试过这样做不起作用(我仍然从dbo.CIS表中获取两行)

SELECT
 c.CarID,
 c.Make,
 c.Model,
 cis.U1,
 cis.U2,
 cis.U3,
 cis.U4,
 cis.U5
 ....
 cis.U22
FROM
 dbo.Car c
LEFT JOIN
 (SELECT
  MAX(Dist) AS Dist,
  U1, 
  U2,
  U3, 
  U4, 
  U5
  ... 
  U22
  FROM dbo.CIS
  GROUP BY
  U1, 
  U2,
  U3, 
  U4, 
  U5
  ... 
  U22
  ) AS cis
ON
 cis.CarID = c.CarID
WHERE c.CarID = 23

如何只返回包含来自Car表(顺便说一下没有重复项)的信息的1行和CIS表,它们可能有重复或根本没有信息给定的CarID。我想从CIS表中返回数据,其中Dist列在存在重复项时具有最高值。

我应该补充一点,这只是一个涉及许多表和连接的相当大的SQL查询的片段。因此,我需要在同一个查询中使用任何解决方案而不是单独创建临时表。

3 个答案:

答案 0 :(得分:9)

以下是利用ROW_NUMBER进行此操作的一种方法。

with myCte as
(
    select ROW_NUMBER() over(partition by CarID order by Dist desc) as RowNum
        , CarID
        , Dist
        , U1
        , U2
    from CIS
)

select * --Your column names here
from Car c
join myCte cis on c.CarID = cis.CarID and cis.RowNum = 1

答案 1 :(得分:1)

这使用公用表表达式来查找dbo.CIS表的匹配行条件。然后,您可以使用dbo.CIScarID

轻松加入Max(dist)表格
WITH idMaxPair AS (
    SELECT carId, MAX(dist) as dist
    FROM dbo.CIS
    GROUP BY carId
)
SELECT
    c.CarID,
    c.Make,
    c.Model,
    cis.U1,
    cis.U2,
    cis.U3,
    cis.U4,
    cis.U5
    ....
    cis.U22
FROM
    dbo.Car c
LEFT JOIN idMaxPair
    ON idMaxPair.carId = c.CarID
INNER JOIN dbo.CIS cis
    ON cis.carId = idMaxPair.carId
    AND cis.dist = idMaxPair.dist
WHERE c.CarID = 23

答案 2 :(得分:1)

由于您使用SQL 2012如何使用FIRST_VALUE窗口函数:

SELECT DISTINCT
 c.CarID,
 c.Make,
 c.Model,
 FIRST_VALUE(cis.dist) OVER (PARTITION BY cis.CarId ORDER BY CIS.Dist DESC) AS dist,
 FIRST_VALUE(cis.U1) OVER (PARTITION BY cis.CarId ORDER BY CIS.Dist DESC) AS U1,
 FIRST_VALUE(cis.U2) OVER (PARTITION BY cis.CarId ORDER BY CIS.Dist DESC) AS U2,
 FIRST_VALUE(cis.U3) OVER (PARTITION BY cis.CarId ORDER BY CIS.Dist DESC) AS U3,
 FIRST_VALUE(cis.U4) OVER (PARTITION BY cis.CarId ORDER BY CIS.Dist DESC) AS U4,
 FIRST_VALUE(cis.U5) OVER (PARTITION BY cis.CarId ORDER BY CIS.Dist DESC) AS U5,
 FIRST_VALUE(cis.U22) OVER (PARTITION BY cis.CarId ORDER BY CIS.Dist DESC) AS U22
FROM
 dbo.Car c
LEFT JOIN dbo.CIS
    ON CIS.CarId = c.CarId
WHERE c.CarID = 23 

这导致:

CarID   Make    Model   dist    U1  U2  U3  U4  U5  U22
23      Volvo   XC90    1170    68  93  24  23  19  93