mysql - 复杂的SQL join 根据给定的结构进行查询

标签 mysql sql database join

我有两个表postscategory_relationships。我需要根据以下逻辑从中获得一些复杂的结果集。

帖子表

id   |      post  
-----|------------------------------|
1000 | Lorem ipsum dolor sit amet   | 
1001 | consectetur adipiscing elit  | 
1002 | sed do eiusmod tempor  ut    | 
1004 | abore et dolore magna aliqua | 

category_relationships 表

post_id    cat_id  
---------|---------|
   1000  |   201   | 
   1000  |   202   | 
   1000  |   211   | 
   1001  |   201   | 
   1001  |   211   | 
   1002  |   202   | 
   1002  |   212   | 

首先,我将尝试解释我的类别结构。我有如下三层结构。 (为了简单起见,我在这里不包含任何类别表)

flight [level 1] [ID : 100]
    - class      [level 2] [ID : 200]
        -- economy  [level 3] [ID : 201]
        -- business [level 3] [ID : 202]
        -- first    [level 3] [ID : 203]
    - alliance   [level 2] [ID : 210]
        -- star     [level 3] [ID : 211]
        -- oneworld [level 3] [ID : 212]
        -- skyteam  [level 3] [ID : 213]

现在的算法:

我需要根据以下规则获取标记为 flight 类别或任何子项的所有帖子。

我需要排除标记为经济 (ID:201) 的帖子;

  1. 但是,如果其同级之一(businessfirst)被标记,它仍应位于结果集中。
  2. 如果在同一帖子中也标记了经济,则不应考虑标记了alliance 或其子级的帖子

请注意,我可以根据结构获取类别 ID 并在查询中使用它们。

到目前为止我的方法:

SELECT posts.ID FROM posts  
LEFT JOIN category_relationships AS tt1 ON (posts.ID = tt1.post_id) 
WHERE tt1.cat_id IN (100,200,201,202,203,210,211,212,213) 
AND posts.ID NOT IN ( SELECT post_id FROM category_relationships WHERE cat_id IN (201) ) 

但这里的问题是它删除了所有标记为经济的帖子。然而它不符合规则 1。

理想的结果集如下所示;

1000 - rule number 1
1002 - anyway no `economy` tagged

不包括:

1001 - rule number 2
1004 - no tagged

希望您对这个问题有清楚的了解,并且我们将非常感谢您的帮助。

最佳答案

因此,您的条件之一是“它没有类别 201 或者它有类别 202 或 203”。您缺少 OR 条件 OR tt1.cat_id IN (202, 203):

SELECT DISTINCT posts.ID FROM posts  
JOIN category_relationships AS tt1 ON (posts.ID = tt1.post_id) 
WHERE tt1.cat_id IN (100,200,201,202,203,210,211,212,213) 
AND (
    posts.ID NOT IN ( SELECT post_id FROM category_relationships WHERE cat_id IN (201) ) 
  OR
    tt1.cat_id IN (202, 203)
  )

请注意,您的 LEFT JOIN 没有任何意义,将由引擎转换为 INNER JOIN。

但是 - 我会按以下方式编写查询:

SELECT posts.ID
FROM posts  
JOIN category_relationships AS tt1 ON posts.ID = tt1.post_id
WHERE tt1.cat_id IN (100,200,201,202,203,210,211,212,213) 
GROUP BY posts.ID
HAVING SUM(tt1.cat_id = 201) = 0
    OR SUM(tt1.cat_id = 202) > 0
    OR SUM(tt1.cat_id = 203) > 0

关于mysql - 复杂的SQL join 根据给定的结构进行查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55116515/

相关文章:

mysql - 组函数与 AVG 函数的使用无效

java - jooq 可以用来比较两个模式是否相同吗?

mysql - 删除表中第一行后如何保持一致性。 MySQL

asp.net - SQL Server 上的数据库有多少?

javascript - 带有 REST API 和 ACL 的云端数据库

database - 使用 BLOB 进行在线备份的速度

php - mysql 粘贴一长串值

php - ü 等外来字符不要进入 Mysql

mysql - SQL 按 RAND 排序,然后按其他排序

php - MySQL Count 函数 - WHERE 函数响应错误