7

I'm pretty new to SQL and am struggling with a query (using Access, FWIW). I have Googled and searched StackOverflow, but I haven't seen this exact scenario. (That could also be because I don't know the correct search terms.)

I have two pretty simple tables that contain similar data.

table1: state, lname, fname, network
table2: state, lname, fname, network

What I want is to find each person/state combo that match in the two tables plus the networks from each table that the person is in:

state, lname, fname, t1.network, t2.network.  

The person may be in more than one network in each table. I want to see each network (from both tables) that the person belongs to.

I started by using a JOIN as below:

SELECT t1.state, t1.lname, t1.fname, t1.network, t2.network
FROM t1 INNER JOIN t2 
ON t1.fname=t2.fname AND t1.lname=t2.lname AND t1.state=t2.state
GROUP BY t1.state, t1.lname, t1.fname, t1.network, t2.network

I quickly figured out that I get a Cartesian product. So if "NY, Smith, John" was in two networks in t1 and three networks in t2 I would get something like this:

NY, Smith, John, NetworkA, NetworkB
NY, Smith, John, NetworkA, NetworkA
NY, Smith, John, NetworkB, NetworkA
NY, Smith, John, NetworkB, NetworkB
NY, Smith, John, NetworkA, NetworkC
NY, Smith, John, NetworkB, NetworkC

What I really want to see is just:

NY, Smith, John, NetworkA, NetworkA
NY, Smith, John, NetworkB, NetworkB
NY, Smith, John, NULL, NetworkC

Can anyone give me some advice on how to proceed or point me in the right direction?

4

5 回答 5

2

因此,看起来您希望每个表中的所有记录都相同,然后只希望每个表中的记录不同。这意味着您需要 UNION 3 组查询。

尝试这样的事情:

SELECT t1.state, 
   t1.lname, 
   t1.fname, 
   t1.network as t1Network, 
   t2.network as t2Network
FROM table1 t1 
   INNER JOIN table2 t2 
      ON t1.fname=t2.fname 
      AND t1.lname=t2.lname 
      AND t1.state=t2.state
      AND t1.network=t2.network
UNION 
SELECT t1.state, 
   t1.lname, 
   t1.fname, 
   t1.network as t1Network, 
   t2.network as t2Network
FROM table1 t1 
   LEFT JOIN table2 t2 
      ON t1.fname=t2.fname 
      AND t1.lname=t2.lname 
      AND t1.state=t2.state
      AND t1.network=t2.network
WHERE t2.network IS NULL
UNION 
SELECT t2.state, 
   t2.lname, 
   t2.fname, 
   t1.network as t1Network, 
   t2.network as t2Network
FROM table2 t2 
   LEFT JOIN table1 t1
      ON t1.fname=t2.fname 
      AND t1.lname=t2.lname 
      AND t1.state=t2.state
      AND t1.network=t2.network
WHERE t1.network IS NULL

这应该会给你想要的结果。

这是要确认的SQL Fiddle 。

- 编辑

今天不去想——你真的不需要第一个查询。您可以从第二个查询中删除 WHERE 条件,它的工作方式相同。疲劳的 :-)

这是更新后的查询 - 两者都应该可以正常工作,这更容易阅读:

SELECT t1.state, 
   t1.lname, 
   t1.fname, 
   t1.network as t1Network, 
   t2.network as t2Network
FROM table1 t1 
   LEFT JOIN table2 t2 
      ON t1.fname=t2.fname 
      AND t1.lname=t2.lname 
      AND t1.state=t2.state
      AND t1.network=t2.network
UNION 
SELECT t2.state, 
   t2.lname, 
   t2.fname, 
   t1.network as t1Network, 
   t2.network as t2Network
FROM table2 t2 
   LEFT JOIN table1 t1
      ON t1.fname=t2.fname 
      AND t1.lname=t2.lname 
      AND t1.state=t2.state
      AND t1.network=t2.network
WHERE t1.network IS NULL

更新的小提琴

顺便说一句 - 这些都应该在 MSAccess 中工作,因为它支持UNION

祝你好运。

于 2013-01-26T21:25:57.607 回答
0
SELECT DISTINCT t1.state, t1.lname, t1.fname, t1.network, t2.network
FROM t1 INNER JOIN t2 
ON t1.fname=t2.fname AND t1.lname=t2.lname AND t1.state=t2.state
GROUP BY t1.state, t1.lname, t1.fname, t1.network, t2.network

你得到你想要的。

无论如何,几乎每个连接都是从构建笛卡尔积开始的(请参阅内部 SQL Server:查询书)。通常,当您尝试过滤掉数据时,创建的虚拟表将在您使用 distinct 时返回一个 distinct set。实际上,没有停止笛卡尔积。

于 2013-01-26T19:36:10.767 回答
0

在这种情况下,UNION 应该是您最好的选择:

SELECT * FROM t1
UNION
SELECT * FROM t2

(请注意,只有在两个表中的所有列都具有相同类型、相同顺序时,此查询才能按原样工作 - 否则最好指定每个所需的列,而不是使用SELECT *)。

于 2013-01-26T19:37:19.580 回答
0

一种选择是使用完全外连接:

SELECT coalesce(t1.state, t2.state), coalesce(t1.lname, t2.lname), coalesce(t1.fname, t2.fname),
  t1.network, t2.network
FROM t1 FULL OUTER JOIN t2 
ON t1.fname=t2.fname AND t1.lname=t2.lname AND t1.state=t2.state
and t1.network = t2.network

输出:

NY  SMITH   JOHN    A   A
NY  SMITH   JOHN    B   B
NY  SMITH   JOHN    NULL    C  

编辑:我没有看到您正在使用 Access - 这是标准 SQL,但我不知道它是否可以在那里工作。

于 2013-01-26T19:47:27.677 回答
0

你想要的是一个UNION。

我会创建一个查询(在 SQL 视图中),其效果是:

SELECT state, lname, fname, network, network
FROM t1
UNION ALL
SELECT state, lname, fname, network, network
FROM t2

然后我会创建其他查询来查询那个。

我会亲自尝试为您提供更多详细信息,但我没有安装 MS Access。

于 2013-01-26T19:43:02.803 回答