假设我有table1
:
id name
-------------
1 "one"
2 "two"
3 "three"
带有第一个外键的table2
:
id tbl1_fk option value
-------------------------------
1 1 1 1
2 2 1 1
3 1 2 1
4 3 2 1
现在我希望得到一个查询结果:
table1.id | table1.name | option | value
-------------------------------------
1 "one" 1 1
2 "two" 1 1
3 "three"
1 "one" 2 1
2 "two"
3 "three" 2 1
我如何实现这一目标?
我已经尝试过:
SELECT
table1.id,
table1.name,
table2.option,
table2.value
FROM table1 AS table1
LEFT outer JOIN table2 AS table2 ON table1.id = table2.tbl1fk
但结果似乎省略了空值:
1 "one" 1 1
2 "two" 1 1
1 "one" 2 1
3 "three" 2 1
解决:感谢Mahmoud Gamal :(加上GROUP BY) 解决了这个问题
SELECT
t1.id,
t1.name,
t2.option,
t2.value
FROM
(
SELECT t1.id, t1.name, t2.option
FROM table1 AS t1
CROSS JOIN table2 AS t2
) AS t1
LEFT JOIN table2 AS t2 ON t1.id = t2.tbl1fk
AND t1.option = t2.option
group by t1.id, t1.name, t2.option, t2.value
ORDER BY t1.id, t1.name
答案 0 :(得分:7)
您必须使用CROSS JOIN
从第一个表中获取name
的所有可能组合,并从第二个表中获取option
。然后LEFT JOIN
这些与第二个表的组合。类似的东西:
SELECT
t1.id,
t1.name,
t2.option,
t2.value
FROM
(
SELECT t1.id, t1.name, t2.option
FROM table1 AS t1
CROSS JOIN table2 AS t2
) AS t1
LEFT JOIN table2 AS t2 ON t1.id = t2.tbl1_fk
AND t1.option = t2.option
答案 1 :(得分:3)
它没有在Q中指定,但似乎选项应该以某种方式定义一个组。在这种情况下,查询可以只是:
SELECT t1.id, t1.name, t2.option, t2.value
FROM (SELECT generate_series(1, max(option)) AS option FROM table2) o
CROSS JOIN table1 t1
LEFT JOIN table2 t2 ON t2.option = o.option AND t2.tbl1_fk = t1.id
ORDER BY o.option, t1.id;
或者,如果选项没有按顺序编号,则从1
开始:
...
FROM (SELECT DISTINCT option FROM table2) o
...
返回:
id | name | option | value
----+-------+--------+-------
1 | one | 1 | 1
2 | two | 1 | 1
3 | three | |
1 | one | 2 | 1
2 | two | |
3 | three | 2 | 1
CROSS JOIN
和大GROUP BY
。grp
)。WITH t2 AS (
SELECT *, count(step OR NULL) OVER (ORDER BY id) AS grp
FROM (
SELECT *, lag(tbl1_fk, 1, 2147483647) OVER (ORDER BY id) >= tbl1_fk AS step
FROM table2
) x
)
SELECT g.grp, t1.id, t1.name, t2.option, t2.value
FROM (SELECT generate_series(1, max(grp)) AS grp FROM t2) g
CROSS JOIN table1 t1
LEFT JOIN t2 ON t2.grp = g.grp AND t2.tbl1_fk = t1.id
ORDER BY g.grp, t1.id;
结果:
grp | id | name | option | value
-----+----+-------+--------+-------
1 | 1 | one | 1 | 1
1 | 2 | two | 1 | 1
1 | 3 | three | |
2 | 1 | one | 2 | 1
2 | 2 | two | |
2 | 3 | three | 2 | 1
解释复杂版本......
每个集合都以tbl1_fk
< =最后一个集合开始。我用window function lag()
检查了这一点。为了覆盖第一行(没有前一行)的角落情况,我提供了lag()
count()
的默认值。
使用grp
作为聚合窗口函数,我将运行计数添加到每一行,有效地形成组编号(SELECT DISTINCT grp FROM t2) g
。
我可以为每个组获取一个实例:
CROSS JOIN
但是,获得最大值并使用漂亮的biggest possible integer 2147483647
来减少CROSS JOIN
更快。
这个GROUP BY
产生我们需要的行而没有任何剩余。避免以后需要LEFT JOIN t2
。
grp
,除了tbl1_fk
之外,还使用{{1}}来区分它。
按您喜欢的方式排序 - 现在可以使用组号进行排序。
答案 2 :(得分:0)
试试这个
SELECT
table1.id, table1.name, table2.option, table2.value FROM table1 AS table11
JOIN table2 AS table2 ON table1.id = table2.tbl1_fk
答案 3 :(得分:-4)
这就够了:
select * from table1 left join table2 on table1.id = table2.tbl1_fk;