定义:
表1 字段名:a,b,c,d
表2 字段名:e,f,g,h,i,j
我想从每个表中获取前4行。
独立查询
SELECT Table1.* FROM Table1 WHERE 1 LIMIT 0,4 -- Colcount 4
SELECT Table2.* FROM Table2 WHERE 1 LIMIT 0,4 -- Colcount 6
查询的简单UNION失败,因为这两个部分具有不同的列数。
SELECT Table1.*,'' AS i,'' AS j FROM Table1 WHERE 1 LIMIT 0,4
UNION
SELECT Table2.* FROM Table2 WHERE 1 LIMIT 0,4
所以我将在结果集中得到以下字段:
a,b,c,d,i,j
a1,b1,c1,d1,*,*,
a2,b2,c2,d2,*,*,
....
....
e1,f1,g1,h1,i1,j1
e2,f2,g2,h2,i2,j2
问题是Table2的字段名称被Table1覆盖。
SELECT Table1.*,'','','','','','' FROM Table1 WHERE 1 LIMIT 0,4
UNION
SELECT '','','','',Table2.* FROM Table2 WHERE 1 LIMIT 0,4
所以我将在结果集中得到以下字段:
a,b,c,d,i,j
a1,b1,c1,d1,*,*,*,*,*,*,
a2,b2,c2,d2,*,*,*,*,*,*,
....
....
*,*,*,*,e1,f1,g1,h1,i1,j1
*,*,*,*,e2,f2,g2,h2,i2,j2
....
....
问题解决但我得到很多空字段。
是否存在已知的性能问题?
你如何解决这个任务?
是否有解决此问题的最佳做法?
答案 0 :(得分:4)
查询的输出应该是一个表,它是一组行,每行具有相同的列名和类型集。 (有一些DBMS支持不规则的行 - 具有不同的列集,但这不是主流功能。)
你必须决定如何在两组中处理两组具有不同列数的四行。
最简单的选择通常是执行两个独立查询。这两个结果集不具有可比性,不应混淆。
如果选择版本1,则应确定哪组列名称合适,或使用“AS x”列别名创建一组复合名称。
如果您选择版本2,那么您应该命名UNION第一个子句的尾随列;目前,他们都没有名字:
SELECT Table1.*, '' AS e, '' AS f, '' AS g, '' AS h, '' AS i, '' AS j
FROM Table1 WHERE 1 LIMIT 0,4
UNION
SELECT '' AS a, '' AS b, '' AS c, '' AS d, Table2.*
FROM Table2 WHERE 1 LIMIT 0,4
(第二个中的AS注释是多余的,但是是自洽的; UNION的两半明确地具有相同的列标题。)
除了您提供空字符串而不是NULL之外,您选择的符号对应于'OUTER UNION'。你可以在文献的选定部分偶尔找到它(E F Codd in the RM / V2 book; C J Date in critiques of all things OUTER)。 SQL 1999将其作为UNION JOIN提供; SQL 2003删除了UNION JOIN(这很不寻常 - 并且该功能受到了谴责)。
我会使用两个单独的查询。
答案 1 :(得分:3)
最明智的是你的“版本2”,除了使用NULL
而不是空字符串。
答案 2 :(得分:0)
这需要一些思考,然后是一些特定于MySQL的解决方法。概念是这样的:Join将产生您想要的表结构。您真正想要的是没有行“匹配”的完全外部联接。为此,我们需要一种可靠的方法来确保行不匹配,然后,我们必须使用UNION和LEFT JOIN以及一个RIGHT JOIN,以克服MySQL对FULL OUTER JOIN的限制。
MySQL 5.6模式设置:
CREATE TABLE A (a int, b int, c int, d int);
CREATE TABLE B (e int, f int, g int, h int, i int, j int);
INSERT INTO A VALUES (1,1,1,1),(2,2,2,2);
INSERT INTO B VALUES (8,8,8,8,8,8),(9,9,9,9,9,9);
查询1 :
SELECT * FROM
(SELECT * FROM (SELECT "TableA" as unique_field) as Ax CROSS JOIN A) as A
LEFT JOIN
(SELECT * FROM (SELECT "TableB" as unique_field) as Bx CROSS JOIN B) AS B
on A.unique_field=B.unique_field
UNION
SELECT * FROM
(SELECT * FROM (SELECT "TableA" as unique_field) as Ax CROSS JOIN A) as A
RIGHT JOIN
(SELECT * FROM (SELECT "TableB" as unique_field) as Bx CROSS JOIN B) AS B
on A.unique_field=B.unique_field
Results :
| unique_field | a | b | c | d | unique_field | e | f | g | h | i | j |
|--------------|--------|--------|--------|--------|--------------|--------|--------|--------|--------|--------|--------|
| TableA | 1 | 1 | 1 | 1 | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| TableA | 2 | 2 | 2 | 2 | (null) | (null) | (null) | (null) | (null) | (null) | (null) |
| (null) | (null) | (null) | (null) | (null) | TableB | 8 | 8 | 8 | 8 | 8 | 8 |
| (null) | (null) | (null) | (null) | (null) | TableB | 9 | 9 | 9 | 9 | 9 | 9 |
此语法:SELECT * FROM (SELECT 1 as unique_field) as Ax CROSS JOIN A) as A
更容易理解为(SELECT 1 as unique_field, * FROM A) AS A
,但是MySQL不允许*
遵循字段规范。