SQL LEFT JOIN 仅第一行

Posted

技术标签:

【中文标题】SQL LEFT JOIN 仅第一行【英文标题】:SQL LEFT JOIN first row only 【发布时间】:2014-07-17 07:48:00 【问题描述】:

假设我们有这样的数据集:

表:DataTable1

ID      ExperienceId   LanguageId    ...
-------------------------------------------
1       1              1
2       1              2
3       1              3
4       2              1
5       2              2
6       2              3
7       3              1
8       3              2
9       3              3
...

表:DataTable2

ID      SomeId OtherId LanguageId    ...
-------------------------------------------
1       459    1       1
2       459    1       2
3       459    1       3
4       245    2       1
5       245    2       2
6       245    2       3
7       295    3       1
8       295    3       2
9       295    3       3
...

我想加入这些表并只获得 SomeId 列而忽略 LanguageId 列。为了更清楚:

SELECT
    t2.SomeId AS RequiredId
    -- ...other data mainly from t2
FROM DataTable1 AS t1
LEFT JOIN DataTable2 AS t2 
    ON t2.OtherId = t1.ExperienceId 
    AND t2.LanguageId = 
        (SELECT TOP 1 t1.LanguageId
         ORDER BY t1.LanguageId)

这个查询应该返回(如果没有错,很清楚)行:

SomeId    ...
----------------
459       ...
245       ...
295       ...
...

现在它返回三倍相同的数据(只有 LanguageId 不同)。

如果我确定它始终存在,我会尝试使用WHERE t1.LanguageId = 1 过滤它,但我不确定。行可以是LanguageId,从1到3,也可以只有ID 2,等等。行肯定至少有一个LanguageId

现在我的问题是:如何连接具有唯一值且一列完全忽略的表

【问题讨论】:

尝试使用group by LanguageId 【参考方案1】:

将其包装在另一个查询中是否有效?

SELECT RequiredId, <all_the_other_fields> from (
SELECT t2.SomeId AS RequiredId
-- ...other data mainly from t2
FROM DataTable1 AS t1
   LEFT JOIN DataTable2 AS t2 
   ON t2.OtherId = t1.ExperienceId 
   AND t2.LanguageId = 
      (SELECT TOP 1 t1.LanguageId
      ORDER BY t1.LanguageId)
   ) group by RequiredId, <all_the_other_fields> 

或者甚至不首先提取列?

SELECT distinct t2.SomeId AS RequiredId
-- ...other data mainly from t2 BUT not the Language id
FROM DataTable1 AS t1
   LEFT JOIN DataTable2 AS t2 
   ON t2.OtherId = t1.ExperienceId 
   AND t2.LanguageId = 
      (SELECT TOP 1 t1.LanguageId
      ORDER BY t1.LanguageId)

【讨论】:

谢谢,第一种方法效果很好:) EF 有问题,直到我看到我的 GROUP BY 子句在内部查询中,而不是在它之外。改变了它,现在它可以工作了。【参考方案2】:

试试这个:

;with cte as 
(select *, row_number() over (partition by someid order by languageid) rn
 from datatable2)

select * 
from datatable1 dt
left join cte c on dt.experienceid = c.otherid and c.rn = 1

【讨论】:

【参考方案3】:

对于这样的事情,当你需要在子查询CROSS APPLY OR 'OUTER APPLY'中选择top 时非常方便

t2.SomeId AS RequiredId
    -- ...other data mainly from t2
FROM DataTable1 AS t1
OUTER APPLY ( SELECT TOP 1 t1.LanguageId
               FROM DataTable2 
               WHERE DataTable2 .OtherId = t1.ExperienceId 
                AND  t2.LanguageId = t1.LanguageId
             ORDER BY t1.LanguageId
             ) AS t2

【讨论】:

【参考方案4】:

试试这个:

SELECT  DISTINCT t2.SomeId AS RequiredId
        -- ...other data mainly from t2
FROM    DataTable1 AS t1
        LEFT JOIN DataTable2 AS t2 
                  ON t2.OtherId = t1.ExperienceId 
WHERE   t2.LanguageId = t1.LanguageId

【讨论】:

【参考方案5】:

你在找这个吗(小提琴:http://sqlfiddle.com/#!3/811b8/12)?:

SELECT    dt2.*
FROM      DataTable1 dt1 INNER JOIN DataTable2 dt2
          ON dt1.ExperienceID = dt2.OtherID AND
          dt1.LanguageID = dt2.LanguageID
WHERE     dt2.LanguageID = (SELECT MIN(LanguageID) FROM DataTable1);

产生:

ID  SOMEID  OTHERID     LANGUAGEID
1   459     1           1
4   245     2           1
7   295     3           1

【讨论】:

以上是关于SQL LEFT JOIN 仅第一行的主要内容,如果未能解决你的问题,请参考以下文章

SQL - LEFT JOIN 和 WHERE 语句仅显示第一行

SQL Server:与 TOP 1 的 LEFT OUTER JOIN 最多选择一行

SQL Server 中的 LEFT JOIN 与 LEFT OUTER JOIN

SQL JOINSQL INNER JOIN 关键字SQL LEFT JOIN 关键字SQL RIGHT JOIN 关键字SQL FULL JOIN 关键字

sql语句左链接left join--3张表关联

如何使用 LEFT JOIN 查询将 RAW SQL 转换为 DQL