如何做一个;水平活接头“;在MySQL中?(浓缩表)

如何做一个;水平活接头“;在MySQL中?(浓缩表),mysql,sql,Mysql,Sql,我正在寻找一种可能性,以concat或联合两个(或更多)表。我无法联接所有表,因为没有引用,也没有匹配的列。如果我在没有任何“开”的情况下加入,我将得到表1中的所有数据乘以表2中的所有数据(不是我想要的)。因此,我试图用MySQL用户定义的变量提供假rownums,但由于所有表中的数据量不同,我无法比较它们。这有点难以解释。因此,我将提供一些例子 示例1(表1=4行,表2=3行,结果=4行) 示例2(表1=3行,表2=4行,结果=4行) 示例3(表1=3行,表2=4行,表3=2行,结果=4行)

我正在寻找一种可能性,以concat或联合两个(或更多)表。我无法联接所有表,因为没有引用,也没有匹配的列。如果我在没有任何“开”的情况下加入,我将得到表1中的所有数据乘以表2中的所有数据(不是我想要的)。因此,我试图用MySQL用户定义的变量提供假rownums,但由于所有表中的数据量不同,我无法比较它们。这有点难以解释。因此,我将提供一些例子

示例1(表1=4行,表2=3行,结果=4行)

示例2(表1=3行,表2=4行,结果=4行)

示例3(表1=3行,表2=4行,表3=2行,结果=4行)


现在是真正困难的部分。我需要这个作为一个疑问。我不想填写其他临时表格。如果可能的话:-)

我想您是在每个表的密集有序列上加入的,只是按“col1”值排序

这实际上是每个表的秩的完全外部联接

不幸的是,MySQL不支持ROW_NUMBER()分析函数,这使得这一点相对简单:

SELECT *
FROM (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 1") AS T1
FULL OUTER JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 2") AS T2
    ON T2.RowNum = T1.RowNum
FULL OUTER JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 3") AS T3
    ON T3.RowNum = T2.RowNum
ORDER BY COALESCE(T1.RowNum, T2.RowNum, T3.RowNum)
MySQL中有其他选择,但我不熟悉解决方法

就完全外部联接解决方案而言,列组很容易实现,因为已知列组只是自然数:

SELECT *
FROM Numbers
LEFT JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 1") AS T1
    ON T1.RowNum = Numbers.Number
LEFT JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 2") AS T2
    ON T2.RowNum = Numbers.Number
LEFT JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 3") AS T3
    ON T2.RowNum = Numbers.Number
WHERE COALESCE(T1.RowNum, T2.RowNum, T3.RowNum) IS NOT NULL
ORDER BY Numbers.Number

这是一种使用准备好的查询的复杂方法:

SET @r1= (SELECT COUNT(*) FROM table1);
SET @r2= (SELECT COUNT(*) FROM table2);
SET @a=-1;

SET @query= IF (@r1 > @r2, 
    (
        SELECT GROUP_CONCAT(CONCAT(
        'SELECT (SELECT col1 FROM table1 LIMIT ', @a:=@a+1, ', 1) AS col1,
        (SELECT col1 FROM table2 LIMIT ', @a, ', 1) AS col2 FROM table1')
        SEPARATOR ' union ') FROM table1
    ),
    (
        SELECT GROUP_CONCAT(CONCAT(
        'SELECT (select col1 from table1 limit ', @a:=@a+1,', 1) as col1,
        (SELECT col1 FROM table2 LIMIT ', @a, ', 1) AS col2 FROM table2')
        SEPARATOR ' union ') FROM table2
    )
);
PREPARE my_query FROM @query;
EXECUTE my_query;

请注意,这根本不是一种有效的方法,它只是解决了您的问题。

我认为在这种情况下,您无法避免使用临时表……这是用于表示,还是不同表中的数据之间存在某种关系?如果是为了表示,最好对每个表进行一次查询,然后在应用程序层中处理结果。@jishi感谢您的评论。你有关于临时表的例子吗?我不想要1000行代码。也许我缺少一些基本语法:-)存储过程的经典函数?@dnagirl Long-story short。没有应用层。这是一种仅限管理员的视图。@Cade Roux感谢您的回复。ROW_NUMBER()有非常简单的解决方法,但据我所知,完全外部联接没有解决方法:-(@eisberg)我不使用MySQL的另一个原因!(虽然我每年只需要使用一次完全外部联接)-在这种情况下,完全外部联接很容易解决(而且更优雅)。你有你的标准“数字”表,对吗?@Cade Roux不允许启动MySQL vs任何东西-东西:-)表比我在这里显示的要复杂得多,但是的,所有表都可以以某种方式排序,需要在报告中进行比较。@eisberg-我编辑了答案以使用标准数字表。我通常将我的数据填充到100万行。尽管您可能希望在存储过程中执行此操作,但我仍然认为您可以在没有游标和临时表的情况下执行此操作。还可以看到:这个@Cade Roux再次感谢:-)数字表是一个很好的方法,但是由于我必须处理未知数量的行(可能>100000000),这将变得很有趣。我以后一定会试试的。我试过了,只是速度慢了一点,会被越来越多的桌子弄得一团糟。但还是要谢谢你!
SELECT *
FROM (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 1") AS T1
FULL OUTER JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 2") AS T2
    ON T2.RowNum = T1.RowNum
FULL OUTER JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 3") AS T3
    ON T3.RowNum = T2.RowNum
ORDER BY COALESCE(T1.RowNum, T2.RowNum, T3.RowNum)
SELECT *
FROM Numbers
LEFT JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 1") AS T1
    ON T1.RowNum = Numbers.Number
LEFT JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 2") AS T2
    ON T2.RowNum = Numbers.Number
LEFT JOIN (SELECT "Col 1", ROW_NUMBER() (OVER ORDER BY "Col 1") AS RowNum FROM "Table 3") AS T3
    ON T2.RowNum = Numbers.Number
WHERE COALESCE(T1.RowNum, T2.RowNum, T3.RowNum) IS NOT NULL
ORDER BY Numbers.Number
SET @r1= (SELECT COUNT(*) FROM table1);
SET @r2= (SELECT COUNT(*) FROM table2);
SET @a=-1;

SET @query= IF (@r1 > @r2, 
    (
        SELECT GROUP_CONCAT(CONCAT(
        'SELECT (SELECT col1 FROM table1 LIMIT ', @a:=@a+1, ', 1) AS col1,
        (SELECT col1 FROM table2 LIMIT ', @a, ', 1) AS col2 FROM table1')
        SEPARATOR ' union ') FROM table1
    ),
    (
        SELECT GROUP_CONCAT(CONCAT(
        'SELECT (select col1 from table1 limit ', @a:=@a+1,', 1) as col1,
        (SELECT col1 FROM table2 LIMIT ', @a, ', 1) AS col2 FROM table2')
        SEPARATOR ' union ') FROM table2
    )
);
PREPARE my_query FROM @query;
EXECUTE my_query;