Mysql 如果没有第二个连接到第一个连接,如何将第一个连接的筛选器列表中的值添加到第一个连接的结果中,以及添加的行值中?
导言 标题尽可能通用,以扩大受众范围,问题尽可能针对我的问题,尽可能与我的问题相同,这样我可以获得最大的受众覆盖率,但可以获得具体的解决方案 摘要 我缺少了应该显示在所需查询中但没有显示的记录,因为它们不存在于联接的一个表中。我想在不使用第二次联接的情况下完成对丢失记录的添加。下面是我的问题,以及一个最小的完整的可验证示例,得到了预期的结果。详情见下文 问题 如何从联接查询的结果中选择两列,然后使用where子句显示来自联接的结果并显示不匹配的行 从现场 我的in子句中有一列的 不在片场 以尽可能最具时间效率的方式 我想要什么?10行Mysql 如果没有第二个连接到第一个连接,如何将第一个连接的筛选器列表中的值添加到第一个连接的结果中,以及添加的行值中?,mysql,join,set,union,Mysql,Join,Set,Union,导言 标题尽可能通用,以扩大受众范围,问题尽可能针对我的问题,尽可能与我的问题相同,这样我可以获得最大的受众覆盖率,但可以获得具体的解决方案 摘要 我缺少了应该显示在所需查询中但没有显示的记录,因为它们不存在于联接的一个表中。我想在不使用第二次联接的情况下完成对丢失记录的添加。下面是我的问题,以及一个最小的完整的可验证示例,得到了预期的结果。详情见下文 问题 如何从联接查询的结果中选择两列,然后使用where子句显示来自联接的结果并显示不匹配的行 从现场 我的in子句中有一列的 不在片场 以尽可
columna columnb columnc
val01 (null) (null)
val02 2020-01-01 2020-01-01
val03 2020-01-01 2020-01-01
val04 2020-01-01 2020-01-01
val05 2020-01-01 2020-01-01
val06 2020-01-01 2020-01-01
val07 2020-01-01 2020-01-01
val08 2020-01-01 2020-01-01
val09 2020-01-01 2020-01-01
val10 2020-01-01 2020-01-01
num rows returned: 10
我得到了什么?9行-从10行预期中减去一行
columna columnb columnc
val02 2020-01-01 2020-01-01
val03 2020-01-01 2020-01-01
val04 2020-01-01 2020-01-01
val05 2020-01-01 2020-01-01
val06 2020-01-01 2020-01-01
val07 2020-01-01 2020-01-01
val08 2020-01-01 2020-01-01
val09 2020-01-01 2020-01-01
val10 2020-01-01 2020-01-01
num rows returned: 9
我试过什么?
我尝试过联合(下面没有显示,但如果需要,可以添加到问题细节中),从而得到比需要多得多的记录。但从分析上看,主要问题在于我在join上滥用了过滤器,其中不包括columnA上丢失的记录
模式
CREATE TABLE IF NOT EXISTS `tableb` (
`col1` char NOT NULL,
`columna` char(5) NOT NULL,
`columnb` date,
`columnc` date
) DEFAULT CHARSET=utf8;
INSERT INTO `tableb` (`col1`, `columna`, `columnb`, `columnc`) VALUES
('a', 'val01', '2020-01-01', '2020-01-01'),
('b', 'val02', '2020-01-01', '2020-01-01'),
('c', 'val03', '2020-01-01', '2020-01-01'),
('d', 'val04', '2020-01-01', '2020-01-01'),
('e', 'val05', '2020-01-01', '2020-01-01'),
('f', 'val06', '2020-01-01', '2020-01-01'),
('g', 'val07', '2020-01-01', '2020-01-01'),
('h', 'val08', '2020-01-01', '2020-01-01'),
('i', 'val09', '2020-01-01', '2020-01-01'),
('j', 'val10', '2020-01-01', '2020-01-01');
CREATE TABLE IF NOT EXISTS `tablea` (
`col1` char(2) NOT NULL
) DEFAULT CHARSET=utf8;
INSERT INTO `tablea` (`col1`) VALUES
('b'),
('c'),
('d'),
('e'),
('f'),
('g'),
('h'),
('i'),
('j');
预期结果查询:
select desired.columna, desired.columnb, desired.columnc from
(select * from (select 'val01' as columna, null as columnb, null as columnc) `t1` union
select * from (select 'val02' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t2` union
select * from (select 'val03' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t3` union
select * from (select 'val04' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t4` union
select * from (select 'val05' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t5` union
select * from (select 'val06' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t6` union
select * from (select 'val07' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t7` union
select * from (select 'val08' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t8` union
select * from (select 'val09' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t9` union
select * from (select 'val10' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t10`) desired;
#Actual Result
/*Goal: Basically, alongside the join results, I want to
also display the rows from the set of the NOT IN clause based upon
the column, that are not in the result set of the
join, which would show columnb, columnc as null*/
SELECT columna,
columnb,
columnc
FROM tablea a, tableb b # inner join
WHERE a.col1 = b.col1 # on a.col1 = b.col1
AND b.columna IN ('val01', 'val02', 'val03', 'val04', 'val05', 'val06', 'val07', 'val08', 'val09', 'val10')
/*
Presently: Using IN returns 9 rows in this query
*/
UNION
SELECT columna,
columnb,
columnc
FROM tablea a, tableb b # inner join
WHERE a.col1 = b.col1 # on a.col1 = b.col1
AND b.columna NOT IN ('val01', 'val02', 'val03', 'val04', 'val05', 'val06', 'val07', 'val08', 'val09', 'val10')
/*
Presently: Using NOT IN returns 0 rows in this query because my
join is returning result of that join
BUT not adding the values not present in the join from the "not in"
set to the set of results.
*/
GROUP BY b.columna ,find_in_set("b.columna", "val01, val02, val03, val04, val05, val06, val07, val08, val09, val10") # find_in_set is here to adhere to original order of a.col1
实际查询:
select desired.columna, desired.columnb, desired.columnc from
(select * from (select 'val01' as columna, null as columnb, null as columnc) `t1` union
select * from (select 'val02' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t2` union
select * from (select 'val03' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t3` union
select * from (select 'val04' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t4` union
select * from (select 'val05' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t5` union
select * from (select 'val06' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t6` union
select * from (select 'val07' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t7` union
select * from (select 'val08' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t8` union
select * from (select 'val09' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t9` union
select * from (select 'val10' as columna, '2020-01-01' as columnb, '2020-01-01' as columnc) `t10`) desired;
#Actual Result
/*Goal: Basically, alongside the join results, I want to
also display the rows from the set of the NOT IN clause based upon
the column, that are not in the result set of the
join, which would show columnb, columnc as null*/
SELECT columna,
columnb,
columnc
FROM tablea a, tableb b # inner join
WHERE a.col1 = b.col1 # on a.col1 = b.col1
AND b.columna IN ('val01', 'val02', 'val03', 'val04', 'val05', 'val06', 'val07', 'val08', 'val09', 'val10')
/*
Presently: Using IN returns 9 rows in this query
*/
UNION
SELECT columna,
columnb,
columnc
FROM tablea a, tableb b # inner join
WHERE a.col1 = b.col1 # on a.col1 = b.col1
AND b.columna NOT IN ('val01', 'val02', 'val03', 'val04', 'val05', 'val06', 'val07', 'val08', 'val09', 'val10')
/*
Presently: Using NOT IN returns 0 rows in this query because my
join is returning result of that join
BUT not adding the values not present in the join from the "not in"
set to the set of results.
*/
GROUP BY b.columna ,find_in_set("b.columna", "val01, val02, val03, val04, val05, val06, val07, val08, val09, val10") # find_in_set is here to adhere to original order of a.col1
SQL小提琴
使用
左连接和中的条件选择列表:
SELECT tb.columnA,
IF(ta.col1 IS NULL, NULL, tb.columnb) AS columnb,
IF(ta.col1 IS NULL, NULL, tb.columnc) AS columnc
FROM tableb tb
LEFT JOIN tablea ta
ON tb.col1 = ta.col1;
使用CASE
表达式(更通用):
如果我们要连接的列是唯一的,则可以使用doubleLEFT JOIN
:
SELECT tb.columnA,
tb2.columnb,
tb2.columnc
FROM tableb tb
LEFT JOIN tablea ta
ON tb.col1 = ta.col1
LEFT JOIN tableb tb2
ON ta.col1 = tb2.col1;
编辑:
你能帮我回答一下,除了加入,还有什么其他的方法可以完成这个任务吗
使用相关子查询:
SELECT tb.columnA,
CASE WHEN EXISTS (SELECT 1 FROM tablea ta WHERE tb.col1 = ta.col1)
THEN tb.columnb
END AS columnb,
CASE WHEN EXISTS (SELECT 1 FROM tablea ta WHERE tb.col1 = ta.col1)
THEN tb.columnc
END AS columnc
FROM tableb tb
和横向连接
,但与常规左侧连接
相比没有真正的优势:
SELECT tb.columnA,
CASE WHEN s.c IS NOT NULL THEN tb.columnb END AS columnb,
CASE WHEN s.c IS NOT NULL THEN tb.columnc END AS columnc
FROM tableb tb
LEFT JOIN LATERAL (SELECT 1 c FROM tablea ta WHERE tb.col1 = ta.col1 LIMIT 1) s ON TRUE
并使用互斥的联合所有
:
SELECT tb.columnA,
tb.columnB,
tb.columnC
FROM tableb tb
WHERE EXISTS (SELECT 1 FROM tablea ta WHERE ta.col1 = tb.col1)
UNION ALL
SELECT tb.columnA,
NULL AS columnB,
NULL AS columnC
FROM tableb tb
WHERE NOT EXISTS (SELECT 1 FROM tablea ta WHERE ta.col1 = tb.col1)
方法如下:@草莓,感谢您的帮助提醒,在这种情况下,MCRE是非常必要的,以便更清楚地了解当前问题,避免任何语法错误,或回答者不必要的努力。请参阅编辑的sql fiddle-fiddle是一个良好的开端,但是如果您显示了您希望的结果集,这会有所帮助。我们可以看到您开始使用的表,但是很难理解查询的预期结果。有了预期的结果,就更容易理解查询需要做什么了。我将修改fiddle以显示预期的结果,然后再授予赏金。您能否帮助回答除了连接之外是否还有其他方法来完成此任务。@VaheJabagchourian从技术上讲,您可以使用相关子查询(横向是一种连接),但它不会更快、更容易阅读。让我准备一下demo@VaheJabagchourian当然done@VaheJabagchourian这里的挑战是,您需要为希望以这种方式处理的每个列提供CASE表达式。我已经提供了最后的方法,结合了UNION ALL
和EXISTS
Lukasz,非常感谢您的努力和全面的回答。非常感谢。我有两个小时的等待时间来奖励赏金。