1

我正在尝试加入两个这样的表:

表 A

A1, A2, A3
A, 1, 35
A, 1, 70
A, 1, 105

表 B

B1,B2, B3
B, 1, 30
C, 1, 32
D, 1, 40
E, 1, 55
F, 1, 60
G, 1, 77
H, 1, 80

预期的结果是这样的:

A, 1, 35, C, 32
A, 1, 70, F, 60
A, 1, 105, H, 80

也就是说,对于表 A 中的每一行,我只想从表 B 中选择一行,这应该是 B3 值较小但最接近 A3 值的行。

到目前为止,我已经尝试了以下查询:

SELECT A1, A2, A3, B1, B3 FROM A JOIN (SELECT B1, B2, B3 FROM B ORDER BY B2, B3 DESC) AS A ON A.A2 = B.B2 AND A.B3 < A.A3

但是,这会产生如下表格:

A, 1, 35, B, 30
A, 1, 35, C, 32
A, 1, 70, B, 30
A, 1, 70, C, 32
A, 1, 70, D, 40
A, 1, 70, E, 55

等等。我还尝试将 LIMIT 1 添加到内部 SELECT,但这不会产生任何结果。如果我自己运行内部查询(使用 LIMIT 1),我会得到预期的结果。如何更改查询以产生所需的结果?我目前正在使用 sqlite,但想以一种可移植到其他 DBMS 的方式编写它。

4

3 回答 3

1

尝试以下查询:

SELECT 
  a.A1,
  a.A2, 
  a.A3,
  (
    SELECT b.B3
    FROM TableB AS b
    ORDER BY ABS(a.A3 - b.B3)
    LIMIT 1
  ) AS x
FROM TableA AS a;

SQL小提琴

SQL Fiddle 不允许我使用 sqlite,因为我的浏览器不支持它,所以我希望这对你有用。

编辑:这实际上应该给你最接近的价值。77 比 60 更接近 70……但我不知道这是否正是您想要的。

于 2013-03-18T15:25:34.163 回答
1

当您想要初始表中的一行时,您可以考虑在select子句中使用子查询:

select a.*,
       (select b3
        from TableB b
        where b.b3 <= a.a3
        order by b3 desc
        limit 1
       ) as b3
from TableA a

子查询本身称为“相关子查询”,因为该where子句同时引用了内表 ( b) 和外表 ( a)。a.a3它按 b3 对表 b 结果进行排序,过滤掉每一行中除小于或等于的值之外的所有值。返回单个值,因为排序是最接近的limit 1值,小于或等于 中的值a.a3

您的问题说的是最接近的值,但示例结果的最大值小于或等于。

于 2013-03-18T15:48:44.567 回答
0

我没有可用的 SQLite,但以下在 SQL Server 中有效;您应该能够用 LIMIT 替换 TOP。

只要您指定 TOP 1,您应该能够从 select 中的嵌套查询中获取它:

select *, 
   (select top 1 B3 
    from B 
    where B3 <= A3
    order by B3 desc)
from A

编辑:要从 B 添加额外的列,您需要将上述查询嵌套到子查询中:

select t.*, B.B1 from (
select *, 
   (select top 1 B3 
    from B 
    where B3 <= A3
    order by B3 desc) as B3
from A
) as t join B on B.B3 = t.B3
于 2013-03-18T15:27:15.110 回答