【问题标题】:How to select all records from first table and only first matching record from second table?如何从第一个表中选择所有记录,从第二个表中只选择第一个匹配记录?
【发布时间】:2015-08-08 23:17:30
【问题描述】:

从这两个表

FirstTable
Number|
  1   |
  2   |
  3   |
  4   |

SecondTable
Id | Number | Column2 | Column3
--------------------------------
1  |  1     | text1   | text11
2  |  2     | text2   | text12
3  |  3     | text3   | text13
4  |  3     | text4   | text14
5  |  2     | text5   | text15

如何从第一个表中选择所有记录,并且只从第二个表中选择第一个匹配的记录,其中包含空值? 结果应该是这样的:

Result
Number | Column2 | Column3
--------------------------
 1     | text1   | text11
 2     | text2   | text12
 3     | text3   | text13
 4     | null    | null

我试过了:

SELECT FT.Number, ST.Column2, ST.Column3
FROM FirstTable FT LEFT JOIN 
SecondTable ST ON FT.Number = 
(
    SELECT TOP 1 S2.Number FROM SecondTable S2 WHERE S2.Number = FT.Number
)

SELECT min(FT.Number), ST.Column2, ST.Column3
FROM FirstTable FT LEFT JOIN 
SecondTable ST ON FT.Number = ST.Number
GROUP BY ST.Column2, ST.Column3

【问题讨论】:

标签: sql sql-server


【解决方案1】:

您可以在子查询中使用 Row_Number() 执行此操作,如下所示:

SELECT T1.Number, T2.Column1, T2.Column3 
FROM FirstTable T1
LEFT JOIN ( SELECT ID, NUMBER, Colunmn2, Column3,
              ROW_NUMBER() OVER (PARTITION BY Number ORDER BY ID ASC) as NumOrder
            FROM SecondTable
) T2 ON T1.Number = T2.Number AND T2.NumOrder = 1

如果您只运行子查询,您将看到它是如何工作的——它通过值为 1 来“标记”感兴趣的行。然后一个简单的连接就可以工作了。

【讨论】:

  • 这几乎是引用副本的答案。
  • @TabAlleman - 哦。呵呵。没读那个。这是解决问题的方法。
【解决方案2】:

你可以做你第一次尝试的这种变化:

SELECT FT.Number, ST.Column2, ST.Column3
FROM FirstTable FT LEFT JOIN 
SecondTable ST ON ST.Id = 
(
    SELECT TOP 1 S2.Id FROM SecondTable S2 WHERE S2.Number = FT.Number
    ORDER BY S2.Id
)

编辑:

我运行了以下脚本作为测试:

DECLARE @FirstTable TABLE (
  [Number] int
);

DECLARE @SecondTable TABLE (
    Id int IDENTITY(1,1)
,   Number int
,   Column2 varchar(31)
,   Column3 varchar(31)
)

INSERT INTO @FirstTable (Number) VALUES (1), (2), (3), (4);

INSERT INTO @SecondTable (Number, Column2, Column3) VALUES
    (1, 'text1', 'text11')
,   (2, 'text2', 'text12')
,   (3, 'text3', 'text13')
,   (3, 'text4', 'text14')
,   (2, 'text5', 'text15')
;

SELECT FT.Number, ST.Column2, ST.Column3
FROM @FirstTable FT LEFT JOIN 
@SecondTable ST ON ST.Id = 
(
    SELECT TOP 1 S2.Id FROM @SecondTable S2 WHERE S2.Number = FT.Number
    ORDER BY S2.Id
);

我得到了以下结果:

Number  Column2 Column3
1           text1   text11
2           text2   text12
3           text3   text13
4           NULL    NULL

这正是您想要的结果。如果你得到“太多行”,你一定是在实现中犯了一个错误。

【讨论】:

  • 我的查询不可能,但如果这是对更复杂查询的简化,那么问题可能存在于您未显示的部分查询中。
  • 1 text1 text11 1 text2 text12 1 text3 text13 1 text4 text14 1 text5 text15 2 text1 text11 2 text2 text12 2 text3 text13 2 text4 text14 2 text5 text15 3 text1 text11 3 text2 text12 3 text3 text13 3 text4 text14 3 text5 text15 4 NULL NULL
  • 我无法以这种格式关注您的评论,但请查看我的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多