我遇到了类似的问题。有两个表(x值是这样排序的 在增量趋势中!)
表A
id x
1 1
1 3
1 4
1 7
表B
id x
1 2
1 5
我想加入这两个表:
1)在id和
的平等条件下
2)A的每一行应根据x值的绝对差异仅与一行B匹配,反之亦然(一对一关系)(小差行有
更优先匹配)。
仅基于上面的描述,它不是一个清晰的描述,因为如果在一个表中共享一个共同行的两对行具有相同的差异,则无法确定哪一行首先出现。因此,将A定义为" Main"表中,表A中具有较小行号的行总是先行
演示的预期结果:
id A.x B.x abs_diff
1 1 2 1
1 4 5 1
表格结尾(不应考虑A中的两个额外行,因为一对一规则)
我正在使用PostgreSQL,所以我尝试的是DISTINCT ON,但它无法解决。
select distinct on (A.x) id,A.x,B.x,abs_diff
from
(A join B
on A.id=B.id)
order by A.x,greatest(A.x,B.x)-least(A.x,B.x)
你有什么想法,在普通的SQL中似乎很棘手。
答案 0 :(得分:1)
尝试:
select a.id, a.x as ax, b.x as bx, x.min_abs_diff
from table_a a
join table_b b
on a.id = b.id
join (select a.id, min(abs(a.x - b.x)) as min_abs_diff
from table_a a
join table_b b
on a.id = b.id
group by a.id) x
on x.id = a.id
and abs(a.x - b.x) = x.min_abs_diff
小提琴:http://sqlfiddle.com/#!15/ab5ae/5/0
虽然它与您的预期输出不匹配,但我认为根据您所描述的内容输出是正确的,因为您可以看到每对在绝对值为1时存在差异。
编辑 - 根据a到b的顺序尝试以下内容:
select *
from (select a.id,
a.x as ax,
b.x as bx,
x.min_abs_diff,
row_number() over(partition by a.id, b.x order by a.id, a.x) as rn
from table_a a
join table_b b
on a.id = b.id
join (select a.id, min(abs(a.x - b.x)) as min_abs_diff
from table_a a
join table_b b
on a.id = b.id
group by a.id) x
on x.id = a.id
and abs(a.x - b.x) = x.min_abs_diff) x
where x.rn = 1
答案 1 :(得分:1)
针对您目前模棱两可的问题的一种可能解决方案:
SELECT *
FROM (
SELECT id, x AS a, lead(x) OVER (PARTITION BY grp ORDER BY x) AS b
FROM (
SELECT *, count(tbl) OVER (PARTITION BY id ORDER BY x) AS grp
FROM (
SELECT TRUE AS tbl, * FROM table_a
UNION ALL
SELECT NULL, * FROM table_b
) x
) y
) z
WHERE b IS NOT NULL
ORDER BY 1,2,3;
这样,每个a.x
都会被分配下一个更大(或相同)b.x
,除非有另一个a.x
仍然小于下一个b.x
(或同样的。)
为演示案例生成请求的结果。不确定各种含糊不清的案例。