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;通过结果可以发现,为空的记录列,并没有展示。
参考技术Aunion 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 Aunion 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 Aunion 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 BY
或LEFT/INNER JOINS
一样。 Query 也执行分页,使用此命令 ORDER BY [Id] DESC OFFSET 0 ROWS FETCH NEXT 25 ROWS ONLY;
,所有测试(在单个表上和使用 UNION ALL
)都是使用分页(OFFSET
和 FETCH 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 问题,合并两个表,相同的列如果某一行值为空,而对应的另一行值不为空的主要内容,如果未能解决你的问题,请参考以下文章