2015-02-20 4 views
0

Я 2 таблицы именно: 1. downloadedtickets 2. redeemedticketsВыберите не-дублирует записи из 2 таблиц MySQL

Каждая таблица имеет атрибут "TicketID".

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

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

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

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

ответ

2

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

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

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

+0

Вы абсолютно правы. Спасибо. –

1

Необходимо указать и заполнить поле, которое вы подсчитываете. Смотрите ниже:

$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 таблице, и UNIQUE в redeemedtickets таблице ... что может быть так, но мы не имеем эту информацию из спецификации мы были предоставлены. (Если это не так, то COUNT (*) для 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. Таким образом, только те строки, которые будут иметь значение NULL из этой таблицы будет строки из downloadedtickets, которые не имеют соответствия.

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^