【问题标题】:Inner joining a table multiple times内部多次加入一个表
【发布时间】:2013-01-14 14:47:50
【问题描述】:

我正在尝试从几个不同的表创建派生表,如果我执行单个内部联接,一切正常,但是当我添加更多联接时,我无法获得所需的结果。这是我现在得到的:

表结构:

第一个表:

+------------+------------+------+-----+---------+-------+
| Field      | Type       | Null | Key | Default | Extra |
+------------+------------+------+-----+---------+-------+
| TAG_ID     | int(11)    | NO   | PRI | NULL    |       |
| STATUS     | int(11)    | YES  |     | NULL    |       |
| ENABLE     | int(11)    | YES  |     | NULL    |       |
| TIME_STAMP | bigint(20) | YES  |     | NULL    |       |
| VALUE      | float      | YES  |     | NULL    |       |
+------------+------------+------+-----+---------+-------+

第二张桌子:

+--------------------+---------------------+------+-----+------------+----------------+
| Field              | Type                | Null | Key | Default    | Extra          |
+--------------------+---------------------+------+-----+------------+----------------+
| TAG_ID             | int(11)             | NO   | PRI | NULL       | auto_increment |
| TAG_DEV_ID         | int(11)             | NO   |     | NULL       |                |
| TAG_NAME           | varchar(256)        | NO   |     | NA         |                |

.....................

| TAG_TIME_STAMP     | bigint(20) unsigned | NO   |     | 0          |                |
+--------------------+---------------------+------+-----+------------+----------------+

这就是我现在要做的——首先,我在将两个表加入一个大表后创建一个视图:

CREATE VIEW U1_TEMP_TEST AS (SELECT TAG_ID AS TID, VALUE FROM table_1);
CREATE VIEW U1_TEST AS (SELECT * FROM table_2 AS T2 INNER JOIN U1_TEMP_TEST AS T1 ON T2.TAG_ID = T1.TID);

现在我需要将表连接到自身,这样我就可以从不同列中的“VALUE”获取行,我这样做是这样的:

SELECT U1.TAG_DEV_ID, U1.TAG_ID, U1.VALUE, U2.VALUE 
FROM U1_TEST AS U1 
INNER JOIN ((SELECT * FROM U1_TEST 
        WHERE (TAG_ID = 1 OR TAG_ID = 12 OR TAG_ID = 21)) AS U2) 
        ON U1.TAG_DEV_ID = U2.TAG_DEV_ID 
WHERE (U1.TAG_ID = 4 OR U1.TAG_ID = 20 OR U1.TAG_ID = 14) 
GROUP BY U1.TAG_DEV_ID;

我得到了这样的好结果:

+------------+--------+--------+-------+
| TAG_DEV_ID | TAG_ID |  VALUE | VALUE |
+------------+--------+--------+-------+
|          1 |      4 |   -0.5 |   2.1 |
|          2 |     14 |  -12.7 |   0.4 |
|          3 |     20 |   -5.7 |   9.5 |
+------------+--------+--------+-------+

但如果我尝试再添加一个这样的连接:

SELECT U1.TAG_DEV_ID, U1.TAG_ID, U1.VALUE, U2.VALUE, U3.VALUE 
FROM U1_TEST AS U1 
INNER JOIN ((SELECT * FROM U1_TEST 
    WHERE (TAG_ID = 1 OR TAG_ID = 12 OR TAG_ID = 21)) AS U2) 
    ON U1.TAG_DEV_ID = U2.TAG_DEV_ID 
INNER JOIN ((SELECT * FROM U1_TEST 
    WHERE (TAG_ID = 3 OR TAG_ID = 13 OR TAG_ID = 22)) AS U3) 
    ON U1.TAG_DEV_ID = U3.TAG_DEV_ID 
WHERE U1.TAG_ID = 4 OR U1.TAG_ID = 14 OR U1.TAG_ID = 24 
GROUP BY U1.TAG_DEV_ID;

返回的数据不是我所期望的,并不是所有的值都被选中。 也许第二个内部联接有问题,我被这个问题困扰了好几个小时,无法理解为什么单个联接查询工作正常而最后一个没有。

感谢您的帮助!

编辑结果数据:

+------------+--------+-------+-------+-------+
| TAG_DEV_ID | TAG_ID | VALUE | VALUE | VALUE |
+------------+--------+-------+-------+-------+
|          1 |      4 |  -0.5 |     3 |     0 |
|          2 |     14 | -12.7 |   0.5 |   1.6 |
+------------+--------+-------+-------+-------+

我希望它是这样的:

+------------+--------+-------+-------+-------+
| TAG_DEV_ID | TAG_ID | VALUE | VALUE | VALUE |
+------------+--------+-------+-------+-------+
|          1 |      4 |  -0.5 |     3 |     0 |
|          2 |     14 | -12.7 |   0.5 |   1.6 |
|          3 |     21 |     x |     x |     x |
+------------+--------+-------+-------+-------+

【问题讨论】:

  • 您想使用 outer 连接:了解SQL joins
  • 阅读一下。它解释了发生了什么 - stackoverflow.com/a/38578/368186
  • 您也可以发布您的最终查询结果吗?
  • "返回的数据不是我期望的" 你能说明你得到了什么和你期望的吗?

标签: mysql inner-join


【解决方案1】:

像这样使用LEFT JOIN

SELECT 
  U1.TAG_DEV_ID, 
  U1.TAG_ID, 
  U1.VALUE, 
  U2.VALUE, 
  U3.VALUE 
FROM U1_TEST AS U1 
LEFT JOIN U1_TEST AS U2  ON U1.TAG_DEV_ID = U2.TAG_DEV_ID 
                        AND U3.TAG_ID IN(1, 12, 21) 
LEFT JOIN U1_TEST AS U3  ON U1.TAG_DEV_ID = U3.TAG_DEV_ID 
                        AND U3.TAG_ID IN(3, 13, 22) 
WHERE U1.TAG_ID IN(4, 14, 24)
GROUP BY U1.TAG_DEV_ID;

【讨论】:

  • 感谢您的回答!您的查询现在返回预期的 3 行,但它会在最后一行中产生一些奇怪的空值..
  • @rock-ass - 您能否发布一些此视图的示例数据U1_TEST?这会很有帮助。谢谢。
  • 哦,没关系,这是 TAG_ID 的问题,我给了查询正确的 ID,它工作正常。非常感谢!
  • @rock-ass 不客气。
【解决方案2】:

您以错误的方式使用连接。您的 where 子句仅过滤 3 个表之一。您的查询如下所示:

SELECT U1.TAG_DEV_ID, U1.TAG_ID, U1.VALUE, U2.VALUE, U3.VALUE 
FROM U1_TEST AS U1 
INNER JOIN ((SELECT * FROM U1_TEST 
    WHERE (TAG_ID = 1 OR TAG_ID = 12 OR TAG_ID = 21)) AS U2) 
    ON U1.TAG_DEV_ID = U2.TAG_DEV_ID 
INNER JOIN ((SELECT * FROM U1_TEST 
    WHERE (TAG_ID = 3 OR TAG_ID = 13 OR TAG_ID = 22)) AS U3) 
    ON U1.TAG_DEV_ID = U3.TAG_DEV_ID 
WHERE U1.TAG_ID = 4 OR U1.TAG_ID = 14 OR U1.TAG_ID = 24 
GROUP BY U1.TAG_DEV_ID;

问题:

1.) WHERE (TAG_ID = 1 OR TAG_ID = 12 OR TAG_ID = 21)) AS U2) 仅适用于 U2

2.) WHERE (TAG_ID = 3 OR TAG_ID = 13 OR TAG_ID = 22)) AS U3) 仅适用于 U3

因此,根据定义,您希望 Tag_ID = 21 的行不能出现在您的结果中,因为它是 U1 和 U2 的一部分,但您在 U3 的过滤器排除了该记录,并且 U3 中没有任何内容可以加入 Tag_ID = 21.

相反,我会使用如下查询:

SELECT U1.TAG_DEV_ID, U1.TAG_ID, U1.VALUE, U2.VALUE, U3.VALUE 
FROM U1_TEST AS U1 
INNER JOIN TEST AS U2 
ON U1.TAG_DEV_ID = U2.TAG_DEV_ID 
INNER JOIN U3
    ON U1.TAG_DEV_ID = U3.TAG_DEV_ID 
    WHERE (TAG_ID = 1 OR TAG_ID = 12 OR TAG_ID = 21)) AND 
    (TAG_ID = 3 OR TAG_ID = 13 OR TAG_ID = 22)) AND
    U1.TAG_ID = 4 OR U1.TAG_ID = 14 OR U1.TAG_ID = 24 
GROUP BY U1.TAG_DEV_ID;

我没有测试这段代码,但你明白了。

【讨论】:

  • where 子句是这样设计的,因此这些值出现在结果集的适当行/列中。
  • 我已经回答了您原来的问题,即您期望 TAG_ID = 21 的记录。与此同时,您已经解决了您的问题,即 TAG_ID 值。
猜你喜欢
  • 2014-03-05
  • 2012-05-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 2011-10-23
  • 2021-04-01
  • 2011-05-06
  • 1970-01-01
相关资源
最近更新 更多