从多个不存在的表中检索多个列,或在行集合上不匹配(mysql php)

从多个不存在的表中检索多个列,或在行集合上不匹配(mysql php),php,mysql,notin,Php,Mysql,Notin,我想就一个mysql查询寻求本论坛的专业建议,我已经花了几个小时试图把它弄对,但没有用 事情是这样的查询1下面我将从5个表中检索姓名、雇主id、日期、轮班id、轮班标签、轮班时间、门店id、门店名称、角色id和角色标签,tblshift、tblstore、tblrole、tblschedule和员工 表tblshift、tblstore、tblrole和employer通过各自表中的ID链接到tblschedule。php变量empstore和empdate是从表单中发布的值 $query1='

我想就一个mysql查询寻求本论坛的专业建议,我已经花了几个小时试图把它弄对,但没有用

事情是这样的<代码>查询1下面我将从5个表中检索姓名、雇主id、日期、轮班id、轮班标签、轮班时间、门店id、门店名称、角色id和角色标签,
tblshift
tblstore
tblrole
tblschedule
员工

表tblshift、tblstore、tblrole和employer通过各自表中的ID链接到tblschedule。php变量empstore和empdate是从表单中发布的值

$query1='选择a.name、a.empid、b.keydate、c.shiftid、c.SHIFTLABLE、c.shifttime、c.shifttime2、d.storeid、d.storelabel、e.roleid、e.rolelabel作为a,tblschedule作为b,tblshift作为c,tblstore作为d,tblrole为e,其中a.empid=b.empid和b.shiftid=c.shiftid和b.storeid=d.storeid和b.roleid=e.roleid和d.storeid='.$empstore.'和b.keydate=“'.$empdate.'”

上面的查询工作正常,但我还想检索与此查询相反的行,即查询中不存在的行。 我尝试在查询中使用“NOT EXIST”和“NOT IN”语句,但查询无法运行或行不正确。请参阅下面使用“不在”和“不存在”语句的查询。从…起 查询2和查询3时,您会发现我使用了empid、keydate和shiftid,因为它们是tblschedule表中的主键,而其他列都基于这种唯一性

*$query2 = 'select a1.name, a1.empid, b1.keydate, c1.shiftid, c1.shiftlabel, c1.shifttime, c1.shifttime2, d1.storeid, d1.storelabel, e1.roleid, e1.rolelabel from employee as a1, tblschedule as b1, tblshift as c1, tblstore as d1, tblrole as e1 where a1.empid=b1.empid and b1.shiftid=c1.shiftid and b1.storeid=d1.storeid and b1.roleid=e1.roleid'
 . ' where (a1.empid, b1.keydate, c1.shiftid) not in (select a2.empid, b2.keydate, c2.shiftid from employee as a2, tblschedule as b2, tblshift as c2, tblstore as d2, tblrole as e2 where a2.empid=b2.empid and b2.shiftid=c2.shiftid and b2.storeid=d2.storeid and b2.roleid=e2.roleid and d2.storeid='.$empstore.' and b2.keydate ="' . $empdate . '")';


$query3 = 'select a1.name, a1.empid, b1.keydate, c1.shiftid, c1.shiftlabel, c1.shifttime, c1.shifttime2, d1.storeid, d1.storelabel, e1.roleid, e1.rolelabel from employee as a1, tblschedule as b1, tblshift as c1, tblstore as d1, tblrole as e1 where a1.empid=b1.empid and b1.shiftid=c1.shiftid and b1.storeid=d1.storeid and b1.roleid=e1.roleid'
 . ' where not exists (select 1 from employee as a2, tblschedule as b2, tblshift as c2, tblstore as d2, tblrole as e2 where a2.empid=b2.empid and b2.shiftid=c2.shiftid and b2.storeid=d2.storeid and b2.roleid=e2.roleid and d2.storeid='.$empstore.' and b2.keydate ="' . $empdate . '" and a1.empid=a2.empid and b1.keydate=b2.keydate and c1.shiftid=c2.shiftid)';*
查询的复杂部分是,我试图从其他表的多个列中收集数据,并且还根据唯一的列empid、keydate和shiftid过滤数据。我在下面的网站上找到了一些来源,但无法使其正常工作

提前感谢,并期待向在座各位学习

问候,, dennis

最初的“有效”查询的形式如下:

SELECT a.name
     , a.empid
     , b.keydate
     , c.shiftid
     , c.shiftlabel
     , c.shifttime
     , c.shifttime2
     , d.storeid
     , d.storelabel
     , e.roleid
     , e.rolelabel
  FROM employee  a
  JOIN tblschedule  b
    ON b.empid = a.empid
  JOIN tblshift  c
    ON c.shiftid = b.shiftid
  JOIN tblstore  d
    ON d.storeid = b.storeid
  JOIN tblrole  e
    ON e.roleid = b.roleid
 WHERE d.storeid = :empstore
   AND b.keydate = :empdate
这应该相当于OP查询。它只是被重新格式化为更易于解读;用
join
关键字替换连接操作的老式逗号语法,并将连接谓词重新定位到
ON
子句


我不明白为什么OP不能直接否定
WHERE
子句中的谓词。也就是说,将上面查询中的
WHERE
子句替换为如下内容:

 WHERE ( d.storeid <> :empstore )
    OR ( b.keydate <> :empdate OR b.keydate IS NULL )
此查询表示返回q1中的所有行,以及q2中匹配的行,但不包括在q2中找到匹配的行。诀窍是WHERE子句,它在q2.empid中测试空值。连接谓词保证当在q2中找到匹配行时,q2.empid将不为NULL。因此,q2.empid中只有q1中没有匹配行的行才会有空值

q2
将是原始查询;OP不希望返回的行集

q1
将是原始查询,省略
WHERE
子句。所以,所有的行。。。OP想要返回的行以及OP想要排除的行


综上所述,查询可能如下所示:

SELECT q1.*
  FROM ( -- query1 - all rows including those we are going to exclude (omit WHERE clause)
         SELECT a.name
              , a.empid
              , b.keydate
              , c.shiftid
              , c.shiftlabel
              , c.shifttime
              , c.shifttime2
              , d.storeid
              , d.storelabel
              , e.roleid
              , e.rolelabel
           FROM employee  a
           JOIN tblschedule  b
             ON b.empid = a.empid
           JOIN tblshift  c
             ON c.shiftid = b.shiftid
           JOIN tblstore  d
             ON d.storeid = b.storeid
           JOIN tblrole  e
             ON e.roleid = b.roleid
       ) q1 
  LEFT
  JOIN (
         -- query2 - the rows that are going to be excluded
         SELECT a.name
              , a.empid
              , b.keydate
              , c.shiftid
              , c.shiftlabel
              , c.shifttime
              , c.shifttime2
              , d.storeid
              , d.storelabel
              , e.roleid
              , e.rolelabel
           FROM employee  a
           JOIN tblschedule  b
             ON b.empid = a.empid
           JOIN tblshift  c
             ON c.shiftid = b.shiftid
           JOIN tblstore  d
             ON d.storeid = b.storeid
           JOIN tblrole  e
             ON e.roleid = b.roleid
          WHERE d.storeid = :empstore
            AND b.keydate = :empdate
       ) q2
    ON q2.empid   = q1.empid
   AND q2.keydate = q1.keydate
   AND q2.shiftid = q1.shiftid 
 WHERE q2.empid IS NULL


但是,对于这种特殊情况,反连接模式似乎是一种简单地否定WHERE子句中谓词的迂回方式。

感谢您的详细解释和书面回复,很抱歉回复得太晚,因为我正在尝试消化这些信息并尝试使用您的示例

我的最后一个问题是如下和工作

      $query = 'SELECT q1.* FROM (SELECT a.name , a.empid, b.keydate, c.shiftid, c.shiftlabel, c.shittime, c.shittime2, d.storeid, d.storelabel, e.roleid, e.rolelabel FROM tblschedule b JOIN employee a ON b.empid = a.empid JOIN tblshift c ON c.shiftid = b.shiftid JOIN tblstore d ON d.storeid = b.storeid JOIN tblrole e ON e.roleid = b.roleid) q1' 
  .' LEFT JOIN (SELECT a.name , a.empid, b.keydate, c.shiftid, c.shiftlabel, c.shittime, c.shittime2, d.storeid, d.storelabel, e.roleid, e.rolelabel FROM tblschedule b JOIN employee a ON b.empid = a.empid JOIN tblshift c ON c.shiftid = b.shiftid JOIN tblstore d ON d.storeid = b.storeid JOIN tblrole e ON e.roleid = b.roleid WHERE d.storeid ='.$empstore.' AND b.keydate ="'. $empstartdate.'") q2'
   .' ON q2.empid = q1.empid'
   .' AND q2.keydate = q1.keydate'
   .' AND q2.shiftid = q1.shiftid'
   .' WHERE q2.storeid IS NULL and q2.keydate is null and q2.empid is null';
顺便说一句,这是我在这个网站上发布的第一个问题,我该如何将你的答案标记为正确答案


谢谢,祝你今天愉快。

查看加入情况。左关节和内关节如果
keydate
可以为空,并且我们希望“匹配”具有空值的行,我们可以使用MySQL空安全比较器<代码>(宇宙飞船符号)。连接谓词保证
empid
shiftid
不会为空。)。如果这不是OP正在寻找的行集,那么我们需要对规范进行更多的澄清。。。“相反的行”实际上是什么意思。
      $query = 'SELECT q1.* FROM (SELECT a.name , a.empid, b.keydate, c.shiftid, c.shiftlabel, c.shittime, c.shittime2, d.storeid, d.storelabel, e.roleid, e.rolelabel FROM tblschedule b JOIN employee a ON b.empid = a.empid JOIN tblshift c ON c.shiftid = b.shiftid JOIN tblstore d ON d.storeid = b.storeid JOIN tblrole e ON e.roleid = b.roleid) q1' 
  .' LEFT JOIN (SELECT a.name , a.empid, b.keydate, c.shiftid, c.shiftlabel, c.shittime, c.shittime2, d.storeid, d.storelabel, e.roleid, e.rolelabel FROM tblschedule b JOIN employee a ON b.empid = a.empid JOIN tblshift c ON c.shiftid = b.shiftid JOIN tblstore d ON d.storeid = b.storeid JOIN tblrole e ON e.roleid = b.roleid WHERE d.storeid ='.$empstore.' AND b.keydate ="'. $empstartdate.'") q2'
   .' ON q2.empid = q1.empid'
   .' AND q2.keydate = q1.keydate'
   .' AND q2.shiftid = q1.shiftid'
   .' WHERE q2.storeid IS NULL and q2.keydate is null and q2.empid is null';