2013-03-29 11 views
-1

Мне нужно выбрать список записей, но вам нужно пропустить те, которые имеют соответствующие поля в 2 разных таблицах. Вот мой DB структураmysql select from where different

заказов:

| orders_id | customers_id | 
| 100  | 01   | 
| 101  | 20   | 
| 102  | 32   | 
| 103  | 48   | 
| 104  | 99   | 

клиентов (только для справки):

| firstname | lastname | customers_id | 
| John  | Doe  | 20   | 
| Fred  | Flinty | 22   | 
| Mark  | Smith | 32   | 

отзывы:

| customers_id | testimonial | 
| 20   | aaa   | 
| 32   | bbb   | 
| 38   | ccc   | 
| 49   | ddd   | 
| 55   | eee   | 

Итак, мне нужно, чтобы выбрать всех клиентов, находятся в моей таблице «Заказы», ​​но вам нужно пропустить их, если они находятся в моей таблице «Отзывы». В приведенном выше примере мне нужно будет выбрать только клиентов 01, 48 и 99, потому что они не существуют в таблице отзывов.

Это то, что я пытался, но я явно не хватает кое-что:

SELECT c.firstname, c.lastname, c.customers_id, o.orders_id, 
     o.customers_id, s.date_added as status_date 
FROM (orders o, testimonials t) 
JOIN customers c 
ON c.customers_id = o.customers_id 
JOIN status_history s 
ON s.orders_id = o.orders_id 
    and s.orders_status_id = o.orders_status 
    and o.customers_id != t.customer_id 
    order by o.orders_id ASC; 

Может кто-нибудь пожалуйста, скажите мне, что я делаю неправильно и как пропустить клиентов, которые находятся в обеих таблицах (заказы и отзывы) ? Я чувствую, что нахожусь на правильном пути, потому что, если я меняю and o.customers_id != t.customer_id на and o.customers_id = t.customer_id, я получаю только клиентов, которые находятся в обеих таблицах (в данном случае 20 и 32).

ответ

3

Это простой способ.

select c.* from order as o 
join customers as c on o.customers_id = c.customers_id 
where o.customers_id not in(select customers_id from testimonials) 
+0

Ответ @J W имеет более быстрый запрос. Использование 'JOIN' лучше, чем использование' IN'. –

4

Вы можете LEFT JOIN об этом.

Причина использования LEFT JOIN потому, что он будет показывать все записи из таблицы, определенной на стороне левой имеет ли он соответствующую запись или нет на столе определяет на стороне правой. Когда таблица Orders соединена с таблицей testimonials, все записи, которые не имеют соответствия, будут иметь значение null для столбцов таблицы testimonials, и это тот, который вы ищете. Чтобы отфильтровать, нам нужно только получить записи с NULL значением, проверив столбец с IS NULL.

SELECT a.*, b.* 
FROM orders a 
     LEFT JOIN testimonials c 
      ON a.customers_ID = c.customers_ID 
     LEFT JOIN customers b 
      ON a.customers_ID = b.customers_ID 
WHERE c.customers_ID IS NULL 

Для дальнейшего получить больше знаний о присоединяется, любезно перейдите по ссылке ниже:


Добавление INDEX.

Если на реальной базе данных Orders таблицы, а также Testimonials всегда зависит от Customers таблицы, то FOREIGN KEY ограничения следует применять для сохранения ссылочной целостности.

Вот как:

ALTER TABLE Orders ADD CONSTRAINT tb_fk1 
    FOREIGN KEY (Customers_ID) REFERENCES Customers(Customers_ID); 
ALTER TABLE Testimonials ADD CONSTRAINT tb_fk2 
    FOREIGN KEY (Customers_ID) REFERENCES Customers(Customers_ID); 
+0

Благодарим вас за отличное объяснение, но при использовании этого метода я не получаю результатов (допускается исчерпание памяти ...), но решение от Neo, похоже, работает нормально. Спасибо за усилия! – user1078494

+0

У вас нет индекса, определенного на таблицах справа? без этого он будет выполнять полное сканирование таблицы в базе данных, что приведет к ее исчерпанию в больших базах данных. –

+0

Я думаю, что вы правы, ни один индекс не определен для этих таблиц. И да, БД достаточно велика ... о, ну, пока нет никаких недостатков решения Нео, я доволен этим – user1078494

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