Я хотел бы обратиться за профессиональным советом к этому форуму по запросу MySQL, который я потратил несколько часов, пытаясь сделать это правильно, но безрезультатно.
Так и происходит. Query1
ниже которого я получу имя, идентификатор работодателя, дату, идентификатор смены, метку смены, время смены, идентификатор магазина, название магазина, идентификатор роли и метку роли из 5 таблиц, tblshift
, tblstore
, tblrole
, tblschedule
а также employee
,
Таблицы tblshift, tblstore, tblrole и Employer связаны с таблицей 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 от сотрудника как 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 IN’ и ‘NOT EXISTS’ заявлений. От
запрос 2 и 3, вы заметите, что я использовал empid, keydate и shifttid, потому что это первичные ключи в моей таблице 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 и shifttid. Я нашел некоторые источники с этого сайта ниже, но не смог заставить его работать.
Как получить несоответствующие результаты в MySQL
получить противоположные результаты из запроса SELECT
MySQL "Где не в" используя две колонки
Заранее спасибо и с нетерпением ждем, чтобы узнать от всех вас здесь.
С уважением,
Деннис
Исходный запрос, который «работает», имеет форму:
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
пункт.
Я не понимаю, почему ОП не может просто отрицать предикаты в WHERE
пункт. То есть заменить WHERE
предложение в запросе выше с чем-то вроде:
WHERE ( d.storeid <> :empstore )
OR ( b.keydate <> :empdate OR b.keydate IS NULL )
Мне кажется, что бы вернуть множество строк, которые OP хочет вернуть.
Но, может быть, я чего-то не понимаю.
В более общем случае, чтобы исключить из набора строк, возвращаемых запросом, строки, соответствующие строкам, возвращенным другим запросом …
используя анти-присоединиться шаблон является нормативным подходом. Это внешняя операция соединения … возвращает все строки из одного запроса, соответствующие строки из другого запроса, а затем исключая строки, в которых найдено совпадение.
В этом конкретном случае запрос будет иметь такую форму:
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
Этот запрос говорит, что нужно вернуть все строки из q1 вместе с совпадающими строками из q2, но исключая строки, в которых совпадение было найдено в q2. Уловка — это предложение WHERE, которое проверяет значение NULL в q2.empid. Предикат соединения гарантирует нам, что q2.empid будет отличным от NULL, когда в q2 найдена подходящая строка. Таким образом, единственные строки, которые будут иметь значение 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';
Кстати, это первый вопрос, который я разместил на этом сайте, и как мне пометить ваш ответ как правильный.
Спасибо и хорошего дня.