Mysql 根据给定结构的复杂SQL连接查询

Mysql 根据给定结构的复杂SQL连接查询,mysql,sql,database,jointable,Mysql,Sql,Database,Jointable,我有两个表posts和category\u关系。我需要根据下面的逻辑得到一些复杂的结果 帖子表 id | post -----|------------------------------| 1000 | Lorem ipsum dolor sit amet | 1001 | consectetur adipiscing elit | 1002 | sed do eiusmod tempor ut | 1004 | abore et dolore magna

我有两个表
posts
category\u关系
。我需要根据下面的逻辑得到一些复杂的结果

帖子表

id   |      post  
-----|------------------------------|
1000 | Lorem ipsum dolor sit amet   | 
1001 | consectetur adipiscing elit  | 
1002 | sed do eiusmod tempor  ut    | 
1004 | abore et dolore magna aliqua | 
post_id    cat_id  
---------|---------|
   1000  |   201   | 
   1000  |   202   | 
   1000  |   211   | 
   1001  |   201   | 
   1001  |   211   | 
   1002  |   202   | 
   1002  |   212   | 
类别关系表

id   |      post  
-----|------------------------------|
1000 | Lorem ipsum dolor sit amet   | 
1001 | consectetur adipiscing elit  | 
1002 | sed do eiusmod tempor  ut    | 
1004 | abore et dolore magna aliqua | 
post_id    cat_id  
---------|---------|
   1000  |   201   | 
   1000  |   202   | 
   1000  |   211   | 
   1001  |   201   | 
   1001  |   211   | 
   1002  |   202   | 
   1002  |   212   | 
首先,我将尝试解释我的类别结构。我有三层结构,如下所示。(为了简单起见,我这里不包括任何类别表)

现在算法:

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) ) 
我需要根据以下规则将所有帖子标记为
flight
category或任何child/child

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

  • 但是,如果它的一个同级(
    business
    first
    )被标记,则它仍应在结果集中
  • <>代码>经济> <代码>,在相同的帖子中也不应考虑“<代码>联盟>代码>或其子/子的帖子。 请注意,我可以根据结构获取类别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) ) 
    

    但这里的问题是,它正在删除所有标记为
    economy
    的帖子。然而,它并没有满足第1条规则

    理想的结果集如下所示

    1000 - rule number 1
    1002 - anyway no `economy` tagged
    
    不包括:

    1001 - rule number 2
    1004 - no tagged
    

    希望您对这个问题有清晰的认识,任何帮助都将不胜感激。

    将您的条件从where子句移至ON子句

    SELECT posts.ID FROM posts  
    LEFT JOIN category_relationships AS tt1 ON (posts.ID = tt1.post_id) 
    and 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) ) 
    

    将条件从where子句移动到ON子句

    SELECT posts.ID FROM posts  
    LEFT JOIN category_relationships AS tt1 ON (posts.ID = tt1.post_id) 
    and 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) ) 
    

    因此,您的条件之一是“它没有类别201,或者它有类别202或203”。您在(202,203)中缺少该或条件
    或tt1.cat\u id:

    请注意,您的左连接没有意义,将由引擎转换为内部连接

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

    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
    

    因此,您的条件之一是“它没有类别201,或者它有类别202或203”。您在(202,203)
    中缺少该或条件
    或tt1.cat\u id:

    请注意,您的左连接没有意义,将由引擎转换为内部连接

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

    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
    

    这是一个很好的候选
    分组方式
    具有

    SELECT cr.post_id
    FROM category_relationships cr
    GROUP BY cr.post_id
    HAVING SUM(cr.tag_id = 100) > 0 AND        -- flight
           (SUM(cr.tag_id = 201) > 0 OR        -- economy  
            SUM(cr.tag_id IN (202, 203)) > 0   -- business/first
           ) AND
           NOT (SUM(cr.tag_id = 201) > 0 OR    -- economy 
                SUM(cr.tag_id IN (210, 211, 212, 213) = 0  -- alliance
               );
    
    这可能更容易使用标志:

    SELECT cr.post_id
    FROM (SELECT cr.*,
                 (cr.tag_id = 100) as is_flight,
                 (cr.tag_id = 201) as is_economy,
                 (cr.tag_id in (202, 203)) as is_first_business,
                 (cr.tag_id IN (210, 211, 212, 213)) as is_alliance
          FROM category_relationships cr
         ) cr
    GROUP BY cr.post_id
    HAVING SUM(is_flight) > 0 AND
           (SUM(is_economy) > 0 OR  
            SUM(is_business_first) > 0
           ) AND
           NOT (SUM(is_economy) > 0 OR  
                SUM(is_alliance) > 0 
               );
    

    这是一个很好的候选
    分组方式
    具有

    SELECT cr.post_id
    FROM category_relationships cr
    GROUP BY cr.post_id
    HAVING SUM(cr.tag_id = 100) > 0 AND        -- flight
           (SUM(cr.tag_id = 201) > 0 OR        -- economy  
            SUM(cr.tag_id IN (202, 203)) > 0   -- business/first
           ) AND
           NOT (SUM(cr.tag_id = 201) > 0 OR    -- economy 
                SUM(cr.tag_id IN (210, 211, 212, 213) = 0  -- alliance
               );
    
    这可能更容易使用标志:

    SELECT cr.post_id
    FROM (SELECT cr.*,
                 (cr.tag_id = 100) as is_flight,
                 (cr.tag_id = 201) as is_economy,
                 (cr.tag_id in (202, 203)) as is_first_business,
                 (cr.tag_id IN (210, 211, 212, 213)) as is_alliance
          FROM category_relationships cr
         ) cr
    GROUP BY cr.post_id
    HAVING SUM(is_flight) > 0 AND
           (SUM(is_economy) > 0 OR  
            SUM(is_business_first) > 0
           ) AND
           NOT (SUM(is_economy) > 0 OR  
                SUM(is_alliance) > 0 
               );
    

    “问题是它正在删除所有标记为经济的帖子”-为什么这是一个问题?这是一个要求——“我需要排除标记为经济(ID:201)的帖子”@PaulSpiegel很抱歉混淆,实际上根据上面的一行,它应该满足我在正文中提到的两条规则。我明白了。。但这并不明显,“问题是它正在删除所有被贴上经济标签的帖子”-为什么这是一个问题?这是一个要求——“我需要排除标记为经济(ID:201)的帖子”@PaulSpiegel很抱歉混淆,实际上根据上面的一行,它应该满足我在正文中提到的两条规则。我明白了。。但这并不明显。@janitgchinthana你的开场白是矛盾的,所以我们不能know@janitgchinthana你的开场白是矛盾的,所以我们不知道或者说条件是有意义的,我想这就是我想要的。或者说条件是有意义的,我想这就是我想要的。