MYSQL 从两个表格中进行选择


MYSQL select from two tabels

I Must to tabels表 A

id | title | content

表 B

id | id_from_table_a | user_id | already_seen

我找不到对mysql的良好查询,它将显示如下内容:

show all from table A  whitout  where user_id='user_logged_id' and  already_seen='yes'

上面的伪代码

这是一个大数据库,所以加入可能是一个更好的解决方案。

这是在没有连接的情况下完成的:

select * from tableA where id not in 
(select id_from_table_a from tableB where user_id='user_logged_id' and  already_seen='yes')

或加入:

select a.id, a.tittle, a.content from tableA a left join tableB b
on a.id = b.id_from_table_a 
where b.user_id <> 'user_logged_id' and  b.already_seen <> 'yes'
group by a.id, a.tittle, a.content

不确定whitout是什么意思,但您可以根据拼写错误更改查询。 我相信这样的东西就是你要找的吗?

SELECT * FROM TableA as a 
    JOIN TableB as b ON a.id = b.id_from_table_a
WHERE 
    b.user_id = 'user_logged_in' AND b.already_seen = 'yes';

这就是我连接 2 张表的方式

 SELECT * FROM TableA
    INNER JOIN TableB on TableA.id=TableB.id_from_table_a 
                      and TableB.user_id='user_logged_id' 
                      and TableB.already_seen='yes'
SELECT * FROM tableA 
JOIN TableB 
ON tableA.id = TableB.tableA-id 
WHERE already-seen = "yes" AND user-id != :user-logged-id

使用反联接模式返回指定结果的查询示例:

SELECT a.id
     , a.title
     , a.content
  FROM table_a a
  LEFT
  JOIN table_b b
    ON b.id_from_table_a = a.id
   AND b.already_seen    = 'yes'
   AND b.user_id         = 'user_logged_in'
 WHERE b.already_seen IS NULL

让我们稍微展开一下。

我们返回table_a中的所有行,以及table_b中的"匹配"行。要被视为"匹配",行必须满足 ON 子句中的谓词(id_from_table_a列必须匹配,already_seen列和user_id列必须满足条件。

LEFT JOIN外连接。它返回左侧表中的所有行(满足 WHERE 子句中的谓词),并从右侧的表中返回匹配的行。(在普通内部联接中,将排除table_a中没有来自table_b的匹配行的行。使用外部连接返回没有匹配项的行。

"诀窍"是排除具有匹配项的行。我们在这里使用WHERE子句中的谓词(条件)来做到这一点。我们正在测试一列,我们知道该列在匹配行上将是非 NULL。(table_b 中的任何匹配行都将具有already_seen列的非 NULL 值,我们保证通过 ON 子句中的条件...对于already_seen列,匹配的行的值均为 'yes'。(我们可以引用table_b中保证为非空的任何列......如果 table_b 中的 id 列被定义为 NOT NULL 或是主键,我们可以使用它。

对于table_a中没有匹配行的行,我们知道already_seen列将被NULL。因此,我们排除所有匹配的行,只保留不匹配的行table_a行。


随访

问:这种反连接是否会比正常情况下产生更快的结果,b.user_id <>"user_logged_id"和b.already_seen <>"是"? – 彩色达内特 5分钟前

答:反联接将给出检查table_b列的不等于条件的查询不同的结果。这些测试会否定LEFT JOIN的"外在性",使其等同于INNER JOIN。反联接模式将返回指定的结果,即table_b中没有"匹配"行的table_a行。

就性能而言,反联接通常是最有效的,尽管其他查询模式也可以同样快。(对于返回相同结果的其他一些查询模式,执行计划是相同的。其他语句可以有不同的执行计划,这些计划通常较慢,但在某些情况下,它们实际上更快。

作为另外两种模式的示例,NOT IN谓词...(请注意,我们需要保证子查询返回的集合中不包含NULL值。

SELECT a.id
     , a.title
     , a.content
  FROM table_a a
 WHERE a.id NOT IN 
       ( SELECT b.id_from_table_a
           FROM table_b b
          WHERE b.already_seen = 'yes'
            AND b.user_id      = 'user_logged_in'
            AND b.id_from_table_a IS NOT NULL
       )

为了完整起见,返回等效结果的NOT EXISTS相关子查询模式的示例:

SELECT a.id
     , a.title
     , a.content
  FROM table_a a
 WHERE NOT EXISTS 
       ( SELECT 1 
           FROM table_b b
          WHERE b.already_seen    = 'yes'
            AND b.user_id         = 'user_logged_in'
            AND b.id_from_table_a = a.id
       )

您可以查看 EXPLAIN SELECT ... 的输出以查看每个语句的实际执行计划。根据 MySQL 的版本,执行计划可能相同,也可能不同。"优化器"(MySQL代码中负责将SQL文本转换为执行计划的部分)在某些主要版本中进行了一些重大更改。