MySQL在两个左连接之间的位置负号
我熟悉LEFT-JOIN/IS-NULL习惯用法,它相当于MySQL中的减号运算符。尽管如此,我已经尝试解决这个问题一段时间了,除了丑陋的子选择之外,没有成功 下面是一个示例结果集来说明问题:MySQL在两个左连接之间的位置负号,mysql,left-join,Mysql,Left Join,我熟悉LEFT-JOIN/IS-NULL习惯用法,它相当于MySQL中的减号运算符。尽管如此,我已经尝试解决这个问题一段时间了,除了丑陋的子选择之外,没有成功 下面是一个示例结果集来说明问题: +-------------------+----------------------------------------------+-----------+ | group_id | valid | not
+-------------------+----------------------------------------------+-----------+
| 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仅教师。我不明白你的评论。你能用产生给定结果的数据编辑你的问题吗?