Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL在两个左连接之间的位置负号_Mysql_Left Join - Fatal编程技术网

MySQL在两个左连接之间的位置负号

MySQL在两个左连接之间的位置负号,mysql,left-join,Mysql,Left Join,我熟悉LEFT-JOIN/IS-NULL习惯用法,它相当于MySQL中的减号运算符。尽管如此,我已经尝试解决这个问题一段时间了,除了丑陋的子选择之外,没有成功 下面是一个示例结果集来说明问题: +-------------------+----------------------------------------------+-----------+ | group_id | valid | not

我熟悉LEFT-JOIN/IS-NULL习惯用法,它相当于MySQL中的减号运算符。尽管如此,我已经尝试解决这个问题一段时间了,除了丑陋的子选择之外,没有成功

下面是一个示例结果集来说明问题:

+-------------------+----------------------------------------------+-----------+
| group_id          | valid                                        | not_valid |
+-------------------+----------------------------------------------+-----------+
| favorites         | AD12,AD17,AD10,AD15,AD13,AD18,AD11,AD16,AD14 | NULL      |
| fruits_veggies    | AD13                                         | NULL      |
| pizza_grill       | AD12,AD10,AD21,AD19,AD11,AD22,AD20           | NULL      |
| salsa_wraps       | NULL                                         | NULL      |
| student_beverages | AD32,AD30,AD31                               | AD31,AD30 |
+-------------------+----------------------------------------------+-----------+
在上面,我想从有效列中删除not_valid中也存在的任何值,因此AD31、AD30应该消失,只留下AD32,因此一个经典的减号运算符:

下面是提供上述结果集的SQL。您知道如何扩展它以从有效SKU中删除所有无效SKU吗

select
    gm.group_id,
    group_concat(pt_include.sku) valid,
    group_concat(pt_exclude.sku) not_valid

from main_menu mm

    left join group_membership gm on 
        mm.master_account_id = gm.master_account_id
        and mm.group_id = gm.group_id

    left join product_tag pt_include on 
        mm.master_account_id = pt_include.master_account_id
        and gm.tag = pt_include.tag and gm.inclusive = '+'

    left join product_tag pt_exclude on 
        mm.master_account_id = pt_exclude.master_account_id
        and gm.tag = pt_exclude.tag and gm.inclusive = '-'

where 
    mm.master_account_id = 321
    and mm.menu_id = 987

group by gm.group_id
后续行动:

为了简洁起见,我在下面删除了所有其他数据。考虑到产品可以被标记为X,Y,Z.。目标是返回标记为XY的项目,而不是Z。可以有任意数量的包容性或排他性标签。用户输入类似+X、+Y、-Z的内容

在我们的示例中,我们希望取回所有标记为饮料的产品,但如果饮料为“仅限教师”,则将其排除在外。因此,这两个连接代表这两个集合:第一个连接所有饮料,第二个连接所有饮料&仅限教师。最终结果应该是第一次连接减去第二次连接

mysql> select * from main_menu;
+-------------------+------------------------+-------------------+
| master_account_id | menu_id                | group_id          |
+-------------------+------------------------+-------------------+
| FA32113145        | 1231                   | student_beverages |
+-------------------+------------------------+-------------------+

mysql> select * from group_membership;
+-------------------+-------------------+--------------+-----------+
| master_account_id | group_id          | tag          | inclusive |
+-------------------+-------------------+--------------+-----------+
| FA32113145        | student_beverages | beverage     | +         |
| FA32113145        | student_beverages | teacher_only | -         |
+-------------------+-------------------+--------------+-----------+

mysql> select * from product_tag;
+-------------------+------+--------------+
| master_account_id | sku  | tag          |
+-------------------+------+--------------+
| FA32113145        | AD30 | beverage     |
| FA32113145        | AD30 | teacher_only |
| FA32113145        | AD31 | beverage     |
| FA32113145        | AD31 | teacher_only |
| FA32113145        | AD32 | beverage     |
+-------------------+------+--------------+

这不需要两个连接。只需使用条件聚合。group_concat将忽略NULL参数,因此您只需对tis使用case语句即可:

select gm.group_id,
       group_concat(case when gm.inclusive = '+' then pt.sku end) as valid,
       group_concat(case when gm.inclusive = '-' then pt.sku end) as not_valid
from main_menu mm left join
     group_membership gm
     on mm.master_account_id = gm.master_account_id and
        mm.group_id = gm.group_id left join
     product_tag pt
     on mm.master_account_id = pt.master_account_id and
        gm.tag = pt.tag and gm.inclusive = '+'
where mm.master_account_id = 321 and
      mm.menu_id = 987
group by gm.group_id;
编辑:

哦,问题是你有两种类型的标记,-和+,在这种情况下,你只希望标记在-列中。我将首先按sku进行聚合,然后按组进行聚合:

select gm.group_id,
       group_concat(case when includeplus = 1 and includeminus = 0 then sku end) as valid,
       group_concat(case when includeminus = 1 then sku end) as invalid
from (select gm.group_id, pt.sku,
             max(gm.include = '+') then includeplus,
             max(gm.include = '-') then includeminus
      from main_menu mm left join
           group_membership gm
           on mm.master_account_id = gm.master_account_id and
              mm.group_id = gm.group_id left join
           product_tag pt
           on mm.master_account_id = pt.master_account_id and
              gm.tag = pt.tag and gm.inclusive = '+'
      where mm.master_account_id = 321 and
            mm.menu_id = 987
      group by gm.group_id, pt.sku
     ) g
group by gm.group_id;

您将逗号分隔的值存储在一个字段中???不,我只是说明两个集合的内容,即pt_include和pt_exclude,这样您就知道我要从另一个字段中排除哪些值。不幸的是,这不起作用。一个产品可以有无限的标签,例如饮料、仅限教师等等。我们想要得到的是所有饮料产品减去仅限教师的产品。mysql>从product_标签中选择*;+-------------+---+---+---+----+|帐户id sku标签+-----------------+--+--123 AD30饮料123 AD31饮料123 AD32饮料123 AD32仅教师。我不明白你的评论。你能用产生给定结果的数据编辑你的问题吗?