mysql - SQL查询按时间顺序获取不同表的两列的组合

标签 mysql sql database data-structures

---------------------------------
| table_one.col_a| table_one.fk |
---------------------------------
| A              | 4            |
---------------------------------
| B              | 4            |
---------------------------------
| C              | 4            |
---------------------------------

---------------------------------
| table_two.col_b|table_two.fk  |
---------------------------------
| E              | 4            |
---------------------------------
| F              | 4            |
---------------------------------
| G              | 4            |
---------------------------------
| H              | 4            |
---------------------------------

我正在寻找一个查询,当 fk 是通用外键时,它会输出类似这样的内容

 A_E
 B_F
 C_G
  _H

最佳答案

您需要使用变量来创建计数器字段:

例如

SELECT  col_a,
        fk,
        @r:= CASE WHEN @FK = fk THEN @r + 1 ELSE 1 END AS RowNumber,
        @fk:= fk
FROM    table_one, 
        (SELECT @fk:= 0) fk,
        (SELECT @r:= 0) r
ORDER BY fk, col_a;

会回来

+-------+----+-----------+
| col_a | fk | RowNumber |
+-------+----+-----------+
|  A    | 4  |    1      |
|  B    | 4  |    2      |
|  C    | 4  |    3      |
+-------+----+-----------+

在这里,您必须首先按分区字段排序,例如如果您希望每个 fk 的行号重置为 1,您必须首先按此顺序排序。然后您的下一个顺序决定了 RowNumber 的应用顺序。因此,如果您更改为:

ORDER BY fk, col_a DESC;

你会得到:

+-------+----+-----------+
| col_a | fk | RowNumber |
+-------+----+-----------+
|  C    | 4  |    1      |
|  B    | 4  |    2      |
|  A    | 4  |    3      |
+-------+----+-----------+

请注意,A 和 C 的行号现在不同

因此,如果您对两个表执行相同的操作,则可以加入 fkRowNumber:

SELECT  b.fk, CONCAT(COALESCE(a.col_a, ''), '_', COALESCE(b.Col_b, '')) AS ColA_ColB
FROM    (   SELECT  col_b,
                    fk,
                    @r:= CASE WHEN @FK = fk THEN @r + 1 ELSE 1 END AS RowNumber,
                    @fk:= fk
            FROM    table_two, 
                    (SELECT @fk:= 0) fk,
                    (SELECT @r:= 0) r
            ORDER BY fk, col_b
        ) b
        LEFT JOIN
        (   SELECT  col_a,
                    fk,
                    @r:= CASE WHEN @FK = fk THEN @r + 1 ELSE 1 END AS RowNumber,
                    @fk:= fk
            FROM    table_one, 
                    (SELECT @fk:= 0) fk,
                    (SELECT @r:= 0) r
            ORDER BY fk, col_a
        ) a
            ON b.fk = a.fk
            AND b.RowNumber = a.RowNumber;

<强> Example on SQL Fiddle

如果您不知道哪个表将包含更多记录,由于 MySQL 不支持完全连接,查询会变得更加复杂,您需要执行 UNION ALL 来合并数据集:

SELECT  a.fk,
        a.RowNumber,
        CONCAT(MAX(CASE WHEN TableSource = 1 THEN Col ELSE '' END), 
                '_',
                MAX(CASE WHEN TableSource = 2 THEN Col ELSE '' END)) AS Col_AB
FROM    ((  SELECT  col_b AS Col,
                    fk,
                    @r:= CASE WHEN @FK = fk THEN @r + 1 ELSE 1 END AS RowNumber,
                    @fk:= fk,
                    2 AS TableSource
            FROM    table_two, 
                    (SELECT @fk:= 0) fk,
                    (SELECT @r:= 0) r
            ORDER BY fk, col_b
        )
        UNION ALL
        (   SELECT  col_a,
                    fk,
                    @r:= CASE WHEN @FK = fk THEN @r + 1 ELSE 1 END AS RowNumber,
                    @fk:= fk,
                    1 AS TableSource
            FROM    table_one, 
                    (SELECT @fk:= 0) fk,
                    (SELECT @r:= 0) r
            ORDER BY fk, col_a
        )) a
GROUP BY a.fk, a.RowNumber;

<强> Example on SQL Fiddle

<小时/>

编辑

感谢Andriy M ,这两个查询可以整理如下:

  • 加入方法:

    SELECT  b.fk, CONCAT(COALESCE(a.col_a, ''), '_', COALESCE(b.Col_b, '')) AS ColA_ColB
    FROM    (   SELECT  col_b,
                        @r:= (@fk = fk) * @r + 1 AS RowNumber,
                        @fk:= fk AS fk
                FROM    table_two, 
                        (SELECT @fk:= 0, @r:= 0) r
                ORDER BY fk, col_b
            ) b
            LEFT JOIN
            (   SELECT  col_a,
                        @r:= (@fk = fk) * @r + 1 AS RowNumber,
                        @fk:= fk AS fk
                FROM    table_one, 
                        (SELECT @fk:= 0, @r:= 0) r
                ORDER BY fk, col_a
            ) a
                ON b.fk = a.fk
                AND b.RowNumber = a.RowNumber;
    
  • 联合方法:

    SELECT  a.fk,
            a.RowNumber,
            CONCAT(MAX(CASE WHEN TableSource = 1 THEN Col ELSE '' END), 
                    '_',
                    MAX(CASE WHEN TableSource = 2 THEN Col ELSE '' END)) AS Col_AB
    FROM    ((  SELECT  col_b AS Col,
                        @r:= (@fk = fk) * @r + 1 AS RowNumber,
                        @fk:= fk AS fk,
                        2 AS TableSource
                FROM    table_two, 
                        (SELECT @fk:= 0, @r:= 0) s
                ORDER BY fk, col_b
            )
            UNION ALL
            (   SELECT  col_a,
                        @r:= (@fk = fk) * @r + 1 AS RowNumber,
                        @fk:= fk AS fk,
                        1 AS TableSource
                FROM    table_one, 
                        (SELECT @fk:= 0, @r:= 0) s
                ORDER BY fk, col_a
            )) a
    GROUP BY a.fk, a.RowNumber;
    

<强> Examples on SQL Fiddle

关于mysql - SQL查询按时间顺序获取不同表的两列的组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19680781/

相关文章:

php - SQLSTATE[42000] : Syntax error while syntax is OK

mysql - 增值税更改 - 如何更改增值税然后将价格四舍五入

mysql - 如何在不获取 maxBooleanClause 异常的情况下查询具有 98,000 个 id 的 SOLR

database - 在数据库中存储加密的用户名哈希

mysql - pk 作为绝对 id 有效吗? ( Django )

mysql - 我如何将我可以插入表中的行数限制为 Mysql 服务器中的一行?

mysql - 当两个表中不存在相似数据时,在一个查询中更新两个表

mysql - 将两个不相关查询的结果合并到一个 View 中

mysql - 如何从一个表中获取具有特定值或不存在于与第一个表具有 1-1 关系的另一个表中的行?

sql - 了解 SQL 中的 JOIN 的好方法或教程