sql union all 问题,合并两个表,相同的列如果某一行值为空,而对应的另一行值不为空

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql union all 问题,合并两个表,相同的列如果某一行值为空,而对应的另一行值不为空相关的知识,希望对你有一定的参考价值。

合并的结果如何

1、创建测试表,

create table test_uni1(id number, value varchar2(20));

create table test_uni2(id number, value varchar2(20));

2、插入测试数据

insert into test_uni1 values (1, 'name1');

insert into test_uni1 values (2, 'name2');

insert into test_uni1 values (3, null);

insert into test_uni2 values (1, 'uni1');

insert into test_uni2 values (2, 'uni2');

insert into test_uni2 values (3, null);

3、查询两张表的UNION ALL情况,select t.* from test_uni1 t union all select t.* from test_uni2 t;

4、编写sql,只查询一列value,且有记录为空的情况;

select value from test_uni1 t union all select value from test_uni2 t;通过结果可以发现,为空的记录列,并没有展示。

参考技术A

union all 不管是否重复,数据都不合并重复行的

而 union 是合并重复行的


比如:

A表:


col1 col2 col3

1    a    (null)

2    b    (null)

3    c    xxx


B表:

col1 col2    col3

1    a    yyy

2    b    (null)

4    d    (null)


那么:

select * from A
union all
select * from B

结果:


col1 col2 col3

1    a    (null)

2    b    (null)

3    c    xxx

1    a    yyy

2    b    (null)

4    d    (null)

select * from A
union all
select * from B

结果:

col1 col2 col3

1    a    (null)

2    b    (null)

3    c    xxx

1    a    yyy

4    d    (null)

本回答被提问者采纳
参考技术B 都存在啊。
加入 a表有两行数据,b表有3行数据,
合并后 的结构是有 5行数据的,
a的数据和b的数据,每行的内容来自a和b表,行的内容不会交叉的。
参考技术C 在字段后面加【javaType=(该字段类型)】,例如:#item.birthday, jdbcType=DATE

SQL Server UNION ALL 合并连接(连接)太慢

【中文标题】SQL Server UNION ALL 合并连接(连接)太慢【英文标题】:SQL Server UNION ALL Merge Join (Concatenation) too slow 【发布时间】:2017-08-17 15:56:58 【问题描述】:

我有一个选择查询,它在两个具有相同结构的表(列和主键,它们具有不同的非聚集索引)上使用 UNION ALL 关键字。这两个表包含 3900 万行,其中一个为 100 万行,另一个为 3800 万行。仅在具有一百万行的 table1 上运行查询时,大约需要 0.2 秒,在 table2 上,我们有不同的情况,最多需要 0.5 到 1.2 秒,具体取决于 DB 的压力。

实际上,为了显示,我需要联合这两个表,但问题是联合查询需要 8 秒才能运行。查看执行计划时,最繁重的操作是 Merge Join (Concatenation),成本为 91%,我有点担心,因为我正在运行的 WHERE 子句从 table1 中选择 51 个条目,从table2(更大的表格)。

我无法理解它,过去两天我一直在努力寻找解决问题的方法,但我发现要么使用 UNION 而不是 UNION ALL,要么使用不必要的子句就像GROUP BYLEFT/INNER JOINS 一样。 Query 也执行分页,使用此命令 ORDER BY [Id] DESC OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY;,所有测试(在单个表上和使用 UNION ALL)都是使用分页(OFFSETFETCH NEXT)关键字执行的。

如果需要,我可以提供表格详细信息和查询详细信息。这是一个简单的选择查询,包含 2 个INNER JOINS 和 2 个LEFT JOINS,所有连接的表都包含非常少量的数据(从 50 个条目到 20K 个条目)。


这是查询

SELECT   *
FROM     (SELECT    tr.Id, 
        tr.Amount, 
        tr.TypeId, 
        t.Name AS [Type], 
        tr.Date, 
        tr.ExternalKey, 
        tr.ExternalDescription, 
        tr.GameId, 
        tr.GameProviderId, 
        gp.Name AS GameProvider, 
        u.Username, 
        u.Pincode, 
        gp.Name, 
        g.GameName, 
        u.OperatorId, 
        tr.BalanceBefore,
        tr.BalanceAfter,
        tr.UserId
FROM ( 
        SELECT    *
              FROM      dbo.ActiveTransactions at
              WHERE    ( 1 = 1 )
         AND ( [Date] >= '2017-07-17 20:00:00' )
         AND ( [TypeId] != 10 )
         AND ( [UserId] = 29041 )
              UNION ALL
              SELECT    *
              FROM      dbo.TransactionHistory th --WITH(INDEX(IX_TransactionHistory_DateType_UserId))
              WHERE    ( 1 = 1 )
         AND ( [Date] >= '2017-07-17 20:00:00' )
         AND ( [TypeId] != 10 )
         AND ( [UserId] = 29041 )
            ) AS tr 

INNER JOIN dbo.Users u ON tr.UserId = u.Id
LEFT JOIN dbo.GameProviders gp ON tr.GameProviderId = gp.Id
LEFT JOIN dbo.Games g ON tr.GameId = g.GameId AND tr.GameProviderId = g.ProviderId 
INNER JOIN dbo.Types t ON tr.TypeId = t.Id     ) AS t
ORDER BY [Id] DESC OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY;

【问题讨论】:

什么是段落?我将包括查询。 考虑在联合之前分别重复连接和过滤 activetransactions 和 transactionhistory,然后联合结果。这应该需要 ..2 + .5 到 1.2 并在 2 秒内完成。它会保存联合操作,直到数据被过滤。 【参考方案1】:

这是一个有根据的猜测:不了解索引或执行计划,引擎实际正在追赶什么。

考虑:在连接/过滤器之后而不是之前进行联合:您必须重复连接,但您可能会在联合集处理中获得一些索引效率损失。

在这种情况下,我创建了两个 CTE,然后将它们联合起来。

因为我无法真正测试这个,我可能有一些语法错误。

WITH cte1 AS 
(SELECT    tr.Id, 
        tr.Amount, 
        tr.TypeId, 
        t.Name AS [Type], 
        tr.Date, 
        tr.ExternalKey, 
        tr.ExternalDescription, 
        tr.GameId, 
        tr.GameProviderId, 
        gp.Name AS GameProvider, 
        u.Username, 
        u.Pincode, 
        gp.Name, 
        g.GameName, 
        u.OperatorId, 
        tr.BalanceBefore,
        tr.BalanceAfter,
        tr.UserId
FROM ( 
        SELECT    *
              FROM      dbo.ActiveTransactions at
              WHERE    ( 1 = 1 )
         AND ( [Date] >= '2017-07-17 20:00:00' )
         AND ( [TypeId] != 10 )
         AND ( [UserId] = 29041 )) AS tr 
INNER JOIN dbo.Users u ON tr.UserId = u.Id
LEFT JOIN dbo.GameProviders gp ON tr.GameProviderId = gp.Id
LEFT JOIN dbo.Games g ON tr.GameId = g.GameId AND tr.GameProviderId = g.ProviderId 
INNER JOIN dbo.Types t ON tr.TypeId = t.Id     ) AS t),
CTE2 as (
SELECT  tr.Id, 
        tr.Amount, 
        tr.TypeId, 
        t.Name AS [Type], 
        tr.Date, 
        tr.ExternalKey, 
        tr.ExternalDescription, 
        tr.GameId, 
        tr.GameProviderId, 
        gp.Name AS GameProvider, 
        u.Username, 
        u.Pincode, 
        gp.Name, 
        g.GameName, 
        u.OperatorId, 
        tr.BalanceBefore,
        tr.BalanceAfter,
        tr.UserId

FROM (SELECT    *
      FROM dbo.TransactionHistory th --WITH(INDEX(IX_TransactionHistory_DateType_UserId))
      WHERE    ( 1 = 1 )
         AND ( [Date] >= '2017-07-17 20:00:00' )
         AND ( [TypeId] != 10 )
         AND ( [UserId] = 29041 ) as tr
INNER JOIN dbo.Users u ON tr.UserId = u.Id
LEFT JOIN dbo.GameProviders gp ON tr.GameProviderId = gp.Id
LEFT JOIN dbo.Games g ON tr.GameId = g.GameId AND tr.GameProviderId = g.ProviderId 
INNER JOIN dbo.Types t ON tr.TypeId = t.Id) AS t
)
SELECT * from CTE1
UNION ALL 
SELECT * from CTE2
ORDER BY [Id] DESC OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY;

【讨论】:

以上是关于sql union all 问题,合并两个表,相同的列如果某一行值为空,而对应的另一行值不为空的主要内容,如果未能解决你的问题,请参考以下文章

请教:SQL同一数据库中,两个查询结果数据类型不同时的union all 合并问题

SQL UNION 和 UNION ALL 操作符

union all的前提是表头相同吗

SQL union all

SQL Union和SQL Union All用法

union和union all的区别