Выберите недублированные записи из 2 таблиц MySQL

У меня есть 2 таблицы, а именно:
1. скачанные карточки
2. выкупить билеты

Каждая таблица имеет атрибут «тикетид».

Я хочу найти людей, которые загрузили их билет, но не выкупили их — по сути, найти недублированные (уникальные) тикетиды.

Мой запрос (PHP) выглядит следующим образом:

$sql = "SELECT ticketid
FROM (
SELECT ticketid
FROM downloadedtickets
UNION ALL
SELECT ticketid
FROM redeemedtickets
)
GROUP BY ticketid
HAVING COUNT(*) = 1";

Я не получаю никакого вывода от этого.

0

Решение

Хороший способ сделать это — левое соединение с тестом на NULL.

SELECT d.ticketid
FROM downloadedtickets d
LEFT JOIN redeemedtickets r USING(ticketid)
WHERE r.ticketid IS NULL

Операция LEFT JOIN создает результирующую строку для каждого загруженного билета и его погашения. Там, где нет погашения, redeemed.ticketid имеет значение NULL, поэтому этот запрос использует WHERE для выбора только этих элементов.

2

Другие решения

Вы должны указать и агрегировать подсчитываемое вами поле. Увидеть ниже:

$sql = "SELECT COUNT(ticketid)ticketid FROM downloadedtickets UNION ALL SELECT ticketid FROM redeemedtickets GROUP BY ticketid HAVING COUNT(ticketid) = 1";
1

Я бы подошел к этому, используя NOT EXISTS, NOT IN, или же LEFT JOIN, Вот последняя версия:

select d.*
from downloadedtickets d left outer join
redeemedtickets r
on d.ticketid = r.ticketid
where r.ticketid is null;
1

Ваш запрос, похоже, должен вернуть указанный результат. Одним из возможных объяснений результатов, которые вы получаете (без строк), является то, что нет загруженных билетов, которые не были погашены.

Этот запрос, кажется, предполагает, что ticketid УНИКАЛЬНО в downloadedtickets стол, и УНИКАЛЬНЫЙ в redeemedtickets таблица … это может иметь место, но у нас нет этой информации из предоставленной нами спецификации. (Если это не так, то СЧЕТ (*) для ticketid от всего downloadedtickets таблица может быть больше единицы.

Является ticketid правильный столбец, чтобы использовать, чтобы «соответствовать» строкам из двух таблиц? Мы предполагаем, что это так, потому что это то, что использует ваш запрос. (Если это не так, это также может объяснить результат, который вы получаете.)

Ваш запрос имеет форму (более легко читаемую):

SELECT t.ticketid
FROM ( SELECT d.ticketid
FROM downloadedtickets d
UNION ALL
SELECT r.ticketid
FROM redeemedtickets r
) t
GROUP BY t.ticketid
HAVING COUNT(*) = 1

Мы отмечаем, что существует вероятность того, что этот запрос может вернуть ticketid для ряда в redeemedtickets это не в downloadedtickets, Может быть какая-то гарантия того, что этого не произойдет, но опять же, эта информация отсутствует в спецификации.

Для больших наборов реализация этого встроенного представления может быть дорогой.

Лично я предпочел бы использовать запрос с более эффективным шаблоном «анти-объединения»:

SELECT d.ticketid
FROM downloadedtickets d
LEFT
JOIN redeemedtickets r
ON r.ticketid = d.ticketid
WHERE r.ticketid IS NULL
ORDER BY d.ticketid

Это, по сути, говорит, вернуть все строки из downloadedticketsвместе с любыми «совпадающими» строками из redeemed Билеты. LEFT Ключевое слово делает это «внешним» соединением, поэтому мы получаем все строки из таблицы с левой стороны, независимо от того, есть ли соответствующие строки из таблицы с правой стороны. Хитрость — это предикат в WHERE предложение, которое отфильтровывает все строки, которые имели совпадение. (Если был матч, мы гарантируем, что ticketid от redeemedtickets будет ненулевым. Таким образом, единственными строками, которые будут иметь значение NULL из этой таблицы, будут строки из downloadedtickets что не было совпадения.

Этот запрос может эффективно использовать индекс redeemedtickets с ведущей колонной ticketid,

Это не единственный запрос, который возвращает указанный результат, существуют другие шаблоны запросов, которые могут возвращать эквивалентный результат.

1
По вопросам рекламы [email protected]