聚合多个select语句而不复制数据

时间:2016-05-09 20:43:11

标签: sql postgresql

如何在不复制数据的情况下聚合2个select子句。

例如,假设我有tab_a包含1到10的数据:

|id|
|1 |
|2 |
|3 |
|. |
|. |
|10|

然后,我想生成tab_btab_c的组合,确保结果有10行,并将tab_a列添加到结果元组

脚本:

SELECT tab_b.id, tab_c.id, tab_a.id
from tab_b, tab_c, tab_a;

然而,对于tab_atab_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      |    

3 个答案:

答案 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