从多个表中检索多个列不存在或匹配行集 (mysql php)
retrieve multiple columns from multiple tables not exists or match on rows set (mysql php)
我想就一个 mysql 问题寻求本论坛的专业建议,我花了几个小时试图解决这个问题,但无济于事。
事情是这样的。 Query1
下面我将从 5 table 秒,tblshift
、tblstore
、tblrole
、tblschedule
和 employee
。
tables tblshift、tblstore、tblrole 和 employer 通过其 tables 中各自的 ID 链接到 tblschedule。 php 变量 empstore 和 empdate 是从表单发布的值。
$query1 = '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 as a, tblschedule as b, tblshift as c, tblstore as d, tblrole as e where a.empid=b.empid and b.shiftid=c.shiftid and b.storeid=d.storeid and b.roleid=e.roleid and d.storeid='.$empstore.'和 b.keydate ="' . $empdate . '"';
上述查询工作正常,但我还想检索与此查询相反的查询,即查询中不存在的行。
我已尝试在查询中使用 'NOT EXIST' 和 'NOT IN' 语句,但查询无法 运行 或行不正确。请查看以下使用 'NOT IN' 和“NOT EXISTS”语句的查询。从
查询 2 和 3,您会发现我使用了 empid、keydate 和 shiftid,因为它们是我的 tblschedule table 中的主键,其他列基于此唯一性。
*$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)';*
查询的复杂部分是我试图从其他 table 的多个列中收集数据,并且我还根据唯一列 empid、keydate 和 shiftid 过滤数据。我从下面这个网站找到了一些资源,但无法正常工作。
How to retrieve non-matching results in mysql
get the opposite results from a SELECT query
mysql "Where not in" using two columns
在此先感谢并期待在这里向大家学习。
问候,
丹尼斯
"works" 的原始查询格式为:
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
关键字替换连接操作的 old-school 逗号语法,并将连接谓词重新定位到 ON
子句。
我不明白为什么 OP 不能直接否定 WHERE
子句中的谓词。也就是说,将上面查询中的 WHERE
子句替换为:
WHERE ( d.storeid <> :empstore )
OR ( b.keydate <> :empdate OR b.keydate IS NULL )
在我看来 return OP 想要 return 的行集 return。
但也许有些地方我不明白。
在更一般的情况下,要从查询 return 的一组行中排除与另一个查询 return 的行相匹配的行...
使用anti-join模式是规范的方法。这是一个外连接操作... return 来自一个查询的所有行,以及来自另一查询的匹配行,然后排除找到匹配项的行。
在这种特殊情况下,查询将采用以下形式:
SELECT q1.*
FROM (
query1
) q1
LEFT
JOIN (
query2
) q2
ON q2.empid = q1.empid
AND q2.keydate = q1.keydate
AND q2.shiftid = q1.shiftid
WHERE q2.empid IS NULL
此查询向 return 查询来自 q1 的所有行,以及来自 q2 的匹配行,但不包括在 q2 中找到匹配的行。诀窍是测试 q2.empid 中的 NULL 值的 WHERE 子句。当在 q2 中找到匹配行时,连接谓词向我们保证 q2.empid 将是 non-NULL。因此,q2.empid 中唯一具有 NULL 值的行是 q1 中没有匹配行的行。
q2
将是原始查询; OP not 想要 return.
的行集
q1
将是原始查询,省略了 WHERE
子句。因此,所有行...OP 想要 return 的行以及 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
但是,对于这种特殊情况,anti-join 模式似乎是一种 round-about 简单地否定 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';
顺便说一下,这是我在本网站上发布的第一个问题,我该如何将您的答案标记为正确答案。
谢谢,祝你有愉快的一天。
我想就一个 mysql 问题寻求本论坛的专业建议,我花了几个小时试图解决这个问题,但无济于事。
事情是这样的。 Query1
下面我将从 5 table 秒,tblshift
、tblstore
、tblrole
、tblschedule
和 employee
。
tables tblshift、tblstore、tblrole 和 employer 通过其 tables 中各自的 ID 链接到 tblschedule。 php 变量 empstore 和 empdate 是从表单发布的值。
$query1 = '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 as a, tblschedule as b, tblshift as c, tblstore as d, tblrole as e where a.empid=b.empid and b.shiftid=c.shiftid and b.storeid=d.storeid and b.roleid=e.roleid and d.storeid='.$empstore.'和 b.keydate ="' . $empdate . '"';
上述查询工作正常,但我还想检索与此查询相反的查询,即查询中不存在的行。 我已尝试在查询中使用 'NOT EXIST' 和 'NOT IN' 语句,但查询无法 运行 或行不正确。请查看以下使用 'NOT IN' 和“NOT EXISTS”语句的查询。从 查询 2 和 3,您会发现我使用了 empid、keydate 和 shiftid,因为它们是我的 tblschedule table 中的主键,其他列基于此唯一性。
*$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)';*
查询的复杂部分是我试图从其他 table 的多个列中收集数据,并且我还根据唯一列 empid、keydate 和 shiftid 过滤数据。我从下面这个网站找到了一些资源,但无法正常工作。
How to retrieve non-matching results in mysql
get the opposite results from a SELECT query
mysql "Where not in" using two columns
在此先感谢并期待在这里向大家学习。
问候, 丹尼斯
"works" 的原始查询格式为:
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
关键字替换连接操作的 old-school 逗号语法,并将连接谓词重新定位到 ON
子句。
我不明白为什么 OP 不能直接否定 WHERE
子句中的谓词。也就是说,将上面查询中的 WHERE
子句替换为:
WHERE ( d.storeid <> :empstore )
OR ( b.keydate <> :empdate OR b.keydate IS NULL )
在我看来 return OP 想要 return 的行集 return。
但也许有些地方我不明白。
在更一般的情况下,要从查询 return 的一组行中排除与另一个查询 return 的行相匹配的行...
使用anti-join模式是规范的方法。这是一个外连接操作... return 来自一个查询的所有行,以及来自另一查询的匹配行,然后排除找到匹配项的行。
在这种特殊情况下,查询将采用以下形式:
SELECT q1.*
FROM (
query1
) q1
LEFT
JOIN (
query2
) q2
ON q2.empid = q1.empid
AND q2.keydate = q1.keydate
AND q2.shiftid = q1.shiftid
WHERE q2.empid IS NULL
此查询向 return 查询来自 q1 的所有行,以及来自 q2 的匹配行,但不包括在 q2 中找到匹配的行。诀窍是测试 q2.empid 中的 NULL 值的 WHERE 子句。当在 q2 中找到匹配行时,连接谓词向我们保证 q2.empid 将是 non-NULL。因此,q2.empid 中唯一具有 NULL 值的行是 q1 中没有匹配行的行。
q2
将是原始查询; OP not 想要 return.
q1
将是原始查询,省略了 WHERE
子句。因此,所有行...OP 想要 return 的行以及 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
但是,对于这种特殊情况,anti-join 模式似乎是一种 round-about 简单地否定 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';
顺便说一下,这是我在本网站上发布的第一个问题,我该如何将您的答案标记为正确答案。
谢谢,祝你有愉快的一天。