如何在不复制数据的情况下聚合2个select子句。
例如,假设我有tab_a
包含1到10的数据:
|id|
|1 |
|2 |
|3 |
|. |
|. |
|10|
然后,我想生成tab_b
和tab_c
的组合,确保结果有10行,并将tab_a
列添加到结果元组
脚本:
SELECT tab_b.id, tab_c.id, tab_a.id
from tab_b, tab_c, tab_a;
然而,对于tab_a
和tab_b
的每个组合,这都是tab_c
的复制数据,我只想添加,并且对于tab_b x tab_c的每个组合,我会添加一行tab_a。
来自tab_b的数据示例
|id|
|1 |
|2 |
来自tab_c的数据示例
|id|
|1 |
|2 |
|3 |
|4 |
|5 |
我想得到这个输出:
|tab_b.id|tab_c.id|tab_a.id|
|1 |1 |1 |
|2 |1 |2 |
|1 |2 |3 |
|... |... |... |
|2 |5 |10 |
答案 0 :(得分:1)
您的问题包括一个未说明的无效假设:表中值的位置(行号)在SQL中是有意义的。不是。在SQL中,行具有无顺序。所有联接 - 事实上 - 一切都基于价值观。要连接表,您必须提供DBMS应使用的值来确定哪些行组合在一起。
您在尝试加入时得到了一些暗示:from tab_b, tab_c, tab_a
。您没有提供任何加入行的基础,这在SQL中意味着没有限制:为了这个连接,所有行都是“相同的”。他们都匹配, voila ,你得到了所有!
要执行您想要的操作,请使用至少一个列重新设计表:用于标识值的键。它可能是一个数字;例如,您的源数据可能是一个数组。更常见的是,每个值都有某种名称。
一旦你有了带键的表,我想你会发现连接更容易编写和理解。
答案 1 :(得分:0)
如果我理解你的问题,也许这就是你要找的......
SELECT bctable.b_id, bctable.c_id, atable.a_id
FROM (SELECT a_id, ROW_NUMBER () OVER () AS arnum FROM a) atable
JOIN (SELECT p.b_id, p.c_id, ROW_NUMBER () OVER () AS bcrnum
FROM ( SELECT b.b_id, c.c_id
FROM b CROSS JOIN c
ORDER BY c.c_id, b.b_id) p) bctable
ON atable.arnum = bctable.bcrnum
请查看SQLFiddle。
答案 2 :(得分:0)
也许你是SQL新手,但这通常不是用RDBMS做的事情。无论如何,如果这是你需要的,PostgreSQL可以很好地处理它,使用不同的策略:
with
tab_a (id) as (select generate_series(1,10)),
tab_b (id) as (select generate_series(1,2)),
tab_c (id) as (select generate_series(1,5))
select tab_b_id, tab_c_id, tab_a.id
from (select *, row_number() over () from tab_a) as tab_a
left join (
select tab_b.id as tab_b_id, tab_c.id as tab_c_id, row_number() over ()
from tab_b, tab_c
order by 2, 1
) tabs_b_c ON (tabs_b_c.row_number = tab_a.row_number)
order by tab_a.id;
with
tab_a (id) as (select generate_series(1,10)),
tab_b (id) as (select generate_series(1,2)),
tab_c (id) as (select generate_series(1,5))
select bc[s][1], bc[s][2], a[s]
from (
select array(
select id
from tab_a
order by 1
) a,
array(
select array[tab_b.id, tab_c.id]
from tab_b, tab_c
order by tab_c.id, tab_b.id
) bc
) arr
join lateral generate_subscripts(arr.a, 1) s on true