从一个表中选择所有列,其中某些列与另一个列匹配,选择

时间:2016-10-04 18:00:33

标签: sql sql-server

我有两个不同的表。有一些共同的列,对于这个例子,我们可以说' name'和' 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与上述查询的结果相匹配。

3 个答案:

答案 0 :(得分:2)

经过大量评论后,我认为这是你之后的......

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)允许我们识别那些匹配的记录,这样它们就可以在cluase中被删除,其中t2.name为null'当t2中没有记录匹配时,它们将始终为null。

因此,您获得的结果集如下: 来自t1的所有记录,在table2中没有名称和id的匹配记录。

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

注意约翰并不像两张桌子那样。我们有来自table1的其他2条记录,以及您之后的表2中的ID,名称。

通常情况下,我会将其作为完整的外连接,但由于我认为你想重用name和id字段来关联同一列中的BOTH表,我们必须使用这种方法并拼出表中的所有列名1,当从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中的任何内容....所以我认为你还想在table1中不存在时仍然显示表2中的ID,Name。

这就是为什么我认为你所追求的是使用union all的第一个查询的结果..

选项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中的name,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)
  1. 假设您要重复使用ID,名称字段;你不能选择*。为什么?因为Table2中的记录不在table1中,而不是table1中的记录。在我的例子中,如果你想要Ringo出现,你必须引用table2!此外,*使您无法" Coalesce" ID和名称字段在一起,就像我在上面的选项3中所做的那样。
  2. 如果你只想要table1中的列,这意味着你永远不会看到table2中的数据...如果你不需要table2中的数据,(例如我的例子中的ringo)那么我们为什么需要要做联盟吗?)我假设你想要ringo,因此你必须在某处引用名称,来自table2的id。

答案 1 :(得分:1)

您也可以使用NOT EXISTS执行此操作:

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

答案 2 :(得分: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