Mysql 执行此查询的正确方法

Mysql 执行此查询的正确方法,mysql,Mysql,我有一张桌子 形式( int id) webformsystemflags(int-id,int-formid,int-sysflagid) sysflag(int-id,name-char(10)) 表单表是包含所有表单的表 webform是一个表,其中包含应用了标志的表单。它有一个外键formid,它是表单表的id,sysflagid是sys flag表的外键 sys flag是包含这些标志的表。假设我有定义为1,2,3的标志 我可以有一些没有应用所有标志的表单,有些可能有1个,有些可能有2

我有一张桌子

形式( int id) webformsystemflags(int-id,int-formid,int-sysflagid)

sysflag(int-id,name-char(10))

表单表是包含所有表单的表

webform是一个表,其中包含应用了标志的表单。它有一个外键formid,它是表单表的id,sysflagid是sys flag表的外键

sys flag是包含这些标志的表。假设我有定义为1,2,3的标志 我可以有一些没有应用所有标志的表单,有些可能有1个,有些可能有2个,有些可能有3个,有些可能没有


如何找到应用了标志1、标志2或标志3的所有表单?

您可以使用
exists
子句来提取如下记录:

select a.*
from form a
where exists (select 1 
              from webformsystemflags 
              where formid = a.id 
              and sysflagid IN (1,2,3))
这不会给您关联的标志。如果您想要:

select a.*, b.sysflagid
from form a
join (select formid, sysflagid
           from webformsystemflags
           where sysflagid in (1,2,3)) b
on a.id = b.formid
有很多不同的方法来解决这个问题

编辑:通过阅读对另一个答案的评论,问题似乎不清楚。您希望结果表单只有一个标志吗?i、 e.表格有标志1,但没有标志2或3

edit2:如果您真的只想要一个true/false查询,只拉取true(有一个标志):

如果需要不带标志的表单:

select a.*
from form a
left join webformsystemflags b on a.id = b.formid
where b.formid is null
edit3:根据注释,具有一个标志而非其他标志的表单:

select a.*
from form a
where exists (select 1 from webformsystemflags where formid = a.id and sysflagid = 1)
and (
  not exists (select 1 from webformsystemflags where formid = a.id and sysflagid = 2)
  or
  not exists (select 1 from webformsystemflags where formid = a.id and sysflagid = 3)
)

您可以使用子查询:

SELECT * FROM `form` WHERE `id` IN (SELECT `formid` FROM `webformsystemflags`)
不过,在处理大型数据库上的子查询时要小心。您可以对连接执行相同的操作,但这是一个简单的解决方案,可以让您继续

或者对于没有特定标志的所有结果:

SELECT * FROM `form` WHERE `id` IN (SELECT `formid` FROM `webformsystemflags` WHERE `sysflagid` != 1 OR `sysflagid` != 2)
或连接方法:

SELECT f.*, r.`sysflagid` FROM `form` f LEFT JOIN `webformsystemflags` r ON r.`formid` = f.`id` WHERE r.`sysflagid` != null
将为您提供表单和相关标志。但是,如果表单上有多个标志,它将不会在一行中获取所有标志。你可能需要在旗子上做一个concat,但是这个答案已经变得不必要的复杂了

*最后编辑*

好的,nutsandbolts-你需要更新你的问题,因为我们两个在许多不同的查询中都超越了自己,而回来说它没有给出正确的结果并没有什么帮助。只需检查我们提供的查询,并使用它们背后的一般逻辑来组合适合您的查询,就可以轻松获得正确的结果

因此,我的最后一个建议是,如果表单应用了某个标记,则需要一个返回表单的查询,而表单应用了其他标记

这里假设您希望所有形式的标志为1,而不是2或3或无:

SELECT f.*, r.`sysflagid` FROM `form` f LEFT JOIN `webformsystemflags` r ON r.`formid` = f.`id` WHERE r.`sysflagid` =1  AND r.`formid` NOT IN (SELECT `formid` FROM `webformsystemflags` WHERE `sysflagid` = 2 OR `sysflagid` = 3)
因为您的WebFraseStultFLAGS是关系型的,这个查询将不返回任何在WebFraseStultFLAGS表中不存在的表单-因此您不需要考虑NULL。
如果这不是你想要的,我强烈建议你重新写下你的问题,并对你的需求进行绝对和完美的澄清,因为在这一次之后,我将退出这次对话。祝你好运。玩得开心。

这是寻找排斥的常见技巧。下面我给出的“FlagYouAreExpectingTo_NOT_Exist”值就是您希望不存在的值。下面是它的工作原理

获取每个表单并左键连接到Web系统标志表,查找匹配的表单和不需要的标志设置。如果找到表单和标志的有效条目,则(wsf)表中的“formid”将存在。因此,我们需要所有不存在的,因此wsf.formid为null的结束符

对于那些尚未标记它的位置,它将为空

select
      f.ID
   from
      forms f
         left join webformsystemflags wsf
            on  f.id = wsf.formid
           AND wsf.sysflagid = FlagYouAreExpectingTo__NOT__Exist
   where
      wsf.formid is null

我很好奇fosco-与我提到的基本子查询相比,该方法的效率如何?我自己从来没有发现需要使用exist子句,而且它在语法上看起来没有必要。然而,它很可能会更有效率。你知道吗?这不是一个讽刺的评论,我真的是curious@KaiQing多年来我一直在使用
exists
子句,它是许多工作的正确工具。我现在无法与您的查询进行比较,因为它没有返回正确的结果。如果您更新您的答案,我可能能够进行一些比较。这表示:“我如何找到所有应用了标志1、标志2或标志3的表单?一些可能应用了1、一些可能应用了2或一些可能应用了3或一些可能没有。”在我的示例中,第一个子查询返回任何具有任何标志的表单。这个问题表明只有12个或3个,因此,是的,我的例子仅限于真或假,而不是具体的1、2或3。如果有无限数量的sysformid,那么它是不准确的。但对于我向你们提出的问题,我想sysflagid只有1、2或3个。为这个可怕的模糊问题增加了额外的可能性。我正在寻找可能没有应用特定标志的表单。所有的查询都给了我正确的结果。我举了一个例子,如果我在表中有一个条目应用了标志1,而没有应用标志2或3,我如何才能得到它们?这将给我应用标志的记录。我需要一个记录,上面有一个特定的标志,这个标志不适用于查看提供的答案,以及你想要什么/不想要什么,就是它。您想知道哪个表单具有标志1、2或3(一个或多个)。。。。或您正在寻找没有特定标志的表单。它们是完全不同的查询。我正在寻找一个没有应用某个/特定标志的表单。我根据您上次的评论更新了我的答案,其中该表单只应用了1个,而没有应用2或3个。从这一点出发,您可以定制查询,以查找表单在何处具有标志2,而不是1或3,依此类推。
select
      f.ID
   from
      forms f
         left join webformsystemflags wsf
            on  f.id = wsf.formid
           AND wsf.sysflagid = FlagYouAreExpectingTo__NOT__Exist
   where
      wsf.formid is null