从一个表中选择所有匹配另一个select的某些列的内容

4
我是一位有用的助手,可以为您翻译文本。
我有两个不同的表格。它们有一些共同的列,例如“名称”和“ID”。
通过进行
(   SELECT name,id FROM table1
    EXCEPT
    SELECT name,id FROM table2)  
UNION ALL
(   SELECT name,id FROM table2
    EXCEPT
    SELECT name,id FROM table1)

我得到了一个列表,其中包含在一个平板电脑上但不在另一个平板电脑上的元素。
到目前为止一切都好。
但是现在,我想从table1中选择所有名称和ID与上述查询结果匹配的内容。

你的意思是从table1中选择符合上述查询条件的结果吗?这不就是在UNION ALL之前的那个查询吗? - kjmerf
是的,但我想要所有的列。 - TiraULTI
好的 - 我已经更新了下面的答案。请告诉我您的想法。 - kjmerf
所以等等,既然这不是mySQL,你可以用full outer join来实现这个功能,并查看记录where (T1.Id or T2.ID is null),以确保来自其中一个的记录不存在于外部。 - xQbert
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - TiraULTI
显示剩余2条评论
3个回答

4

经过许多评论,我认为这就是你想要的...

SELECT T1.* 
FROM table1 t1
LEFT JOIN table2 t2
   on T1.ID = T2.ID
  and T1.Name = T2.Name
  AND E2.event_Time_UTC between  convert(datetime,'2016-02-09 00:00:20',101) and convert(datetime '2016-02-09 23:59:52',101)
WHERE T2.Name is null
 AND E1.Event_Time_UTC between  convert(datetime,'2016-02-09 00:00:20',101) and convert(datetime,'2016-02-09 23:59:52',101)

您可以允许隐式转换,但以上是显式方法。

如果不允许,则需要将字符串日期转换为日期时间,假设Event_Time_UTC是日期/时间数据类型。

左连接使我们可以返回第一个表中的所有记录以及与第二个表匹配的记录。

t1.*仅返回来自table1的列。连接条件(on)允许我们识别匹配的记录,因此它们可以在where子句中通过'where t2.name is null'进行消除,当t2中没有匹配记录时,它们将始终为空。

因此,您将获得一个结果集:从t1中获取所有记录,其中名称和id在table2中没有匹配记录。

enter image description here

旧版本

根据评论,以下内容已不再相关。

我删除了之前的回答,因为您正在使用 SQL Server 而不是 MySQL,并且我知道您想要多个记录而不是连接 table1 和 table2。

下面我创建了两个表:table1 和 table2。然后我用一些示例数据填充了 table1 和 table2。

接下来,我展示了如何仅获取存在于一个表中但不存在于另一个表中的记录;每个记录返回一个单独的 ROW。然后我详细介绍了为什么我选择这种方法而不是其他方法。最后,我将回顾您尝试过的内容,并尝试解释为什么我认为它不会起作用。

create table table1 (
  ID int,
  name varchar(20),
  col1 varchar(20),
  col2 varchar(20),
  col3 varchar(20));

Create table table2 (
  id int,
  name varchar(20));

Insert into table1 values (1,'John','col1','col2','col3');
Insert into table1 values (2,'Paul','col1','col2','col3');
Insert into table1 values (3,'George','col1','col2','col3');

Insert into table2 values (1,'John');
Insert into table2 values (4,'Ringo');

选项1
SELECT T1.name, T1.ID, T1.Col1, T1.Col2, T1.Col3
FROM Table1 T1
LEFT JOIN Table2 T2
 on T1.Name = T2.Name
and T1.ID = T2.ID
WHERE T2.ID is null  

UNION ALL

SELECT T2.name, T2.ID, NULL, NULL, NULL
FROM Table1 T1
RIGHT JOIN Table2 T2   
 on T1.Name = T2.Name
and T1.ID = T2.ID
WHERE T1.ID is null  ;

这导致...

enter image description here

注意,John在两个表中都没有出现。我们从table1中获得了另外两条记录,并且你想要的table2的ID和名称。

通常情况下,我会使用全外连接,但由于我认为你想重用名称和ID字段来关联同一列中的BOTH表,因此我们不得不使用这种方法,并在table1中拼写所有列名,当显示来自table2的记录时,在table1中将每个列放置为NULL,以使第二个查询的输出与第一个查询联合起来。我们无法使用“*”符号。

选项2:使用全外连接...使用T1中的所有列

SELECT T1.*
FROM Table1 T1
FULL OUTER JOIN Table2 T2
 on T1.ID = T2.ID
 and T1.Name = T2.Name
WHERE (T1.ID is null or T2.ID is null)

你得到了这个...它没有显示Ringo...

enter image description here

但我想问为什么您需要从表2获取任何内容,因此我认为当表1中不存在时,您仍希望显示表2的ID、名称。

这就是为什么我认为您需要使用联合所有的第一个查询结果。

选项3,我想我们可以通过执行...来避免选项1中的第二个查询

SELECT coalesce(T1.Name, T2.name) as name, coalesce(T1.Id,T2.ID) as ID, T1.col1, T1.Col2, T1.Col3
FROM Table1 T1
FULL OUTER JOIN Table2 T2
 on T1.ID = T2.ID
 and T1.Name = T2.Name
WHERE (T1.ID is null or T2.ID is null)

这样做是因为我们知道只需要从table2中获取名称和ID,而table1中的所有列值都将为空。

但请注意,在所有情况下,我们都不能使用Tablename.*来选择从table1中选取所有记录。

这样做可以得到我认为所需的结果。

enter image description here

这是你尝试的内容:

(   SELECT name,id FROM table1
    EXCEPT
    SELECT name,id FROM table2)  
UNION ALL
(   SELECT name,id FROM table2
    EXCEPT
    SELECT name,id FROM table1)

假设您想要重复使用ID、Name字段;您无法选择*。为什么?因为Table2中的记录不在Table1中,所以也不在Table1中。在我的示例中,如果您想让Ringo出现,您必须引用Table2!此外,*不能像我在选项3中所做的那样将ID和Name字段"合并"在一起。
如果您只想从Table1中获取列,这意味着您永远不会看到来自Table2的数据。如果您不需要来自Table2的数据(例如,在我的示例中的Ringo),那么我们为什么需要进行联合操作呢?我假设您想要Ringo,因此您必须在某个地方引用Table2中的name、id。

它们的结构并不相同。这就是问题所在,它们有一些共同的列,但也有其他不同的列。我想要来自具有数据的表格中的所有列。 - TiraULTI
那么以上的选项1将会可行。您将从table1中获取所有列/值,以及仅来自table2的name和id,它们出现在与table1相同的列中,并且对于table 1的所有其他列具有空值。如果这不是您想要的结果,则我需要查看来自table1、table2的结果集和数据模拟,并了解期望的结果。 - xQbert
非常感谢。我现在会进行测试,并更新结果。 - TiraULTI
那么您需要的是左连接。答案已在顶部更新。 - xQbert
我正在尝试执行此查询,但无法使其工作。 table1名称为db1中的EVENTS,table2是db2中的EVENTS(它们具有不同的列)。 select * from EVENTS LEFT JOIN ACCESSCONTROLPOSTUP.dbo.events on events.serialnum=accesscontrolpostup.dbo.events.serialnum where accesscontrolpostup.dbo.events.serialnum is null @xqbert - TiraULTI
显示剩余13条评论

1
您可以使用 NOT EXISTS 来完成这个操作:

SELECT *
FROM table1
WHERE
NOT EXISTS
(SELECT 1
 FROM table2
 WHERE table1.id = table2.id
 AND table1.name = table2.name)

好的,我会尝试。谢谢。 - TiraULTI
我在子查询中进行了一次更新,但它不应该影响结果。看起来你可能已经在上面得到了答案,但如果你愿意分享一些样本数据,我们也许可以一起解决问题。这个查询对我来说是有效的。 - kjmerf
@kbball 这如何显示出在第二个查询中指示的表2中而不在表1中的结果,就像原始帖子中的 union 语句一样? - xQbert
1
我的评论已经不再相关,因为根据OP的评论,他真正想要的是从table1中获取不在table2中的记录,而不是相反。 - xQbert
确切地说,这个问题表述很混乱。表2中的唯一记录根本不相关。 - kjmerf
显示剩余3条评论

0
;with cte as
 (
  (   SELECT name,id FROM table1
      EXCEPT
      SELECT name,id FROM table2)  
       UNION ALL
  (   SELECT name,id FROM table2
      EXCEPT
      SELECT name,id FROM table1)
 )
 Select * 
 from table1 as tbl1
 where
    tbl1.id = cte.id
     and tbl1.name = cte.name

将完全相同的查询包装在CTE中并没有任何区别。也许您应该尝试解释一下您想要实现什么以及这个答案如何帮助您。 - Stephen Turner
请问您能解释一下cte是什么吗? - TiraULTI
CTE是公共表达式。从高层次来看,它是一种查询内部CTE返回的结果的方法。快速的谷歌搜索将为您提供大量关于它的信息。 - luke
@luke。这个查询如何显示table2中不存在于table1中的记录?(即联合查询中第二个查询的结果) - xQbert
好的,我对问题有不同的理解,我会在主问题评论中寻求澄清。考虑一下:为什么你要将table2中不在table1中的结果联合起来,然后又不使用它们做任何事情呢? - xQbert
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接