Silverstripe leftJoin ГДЕ два значения

#mysql #sql #silverstripe

#mysql #sql #silverstripe

Вопрос:

У меня есть отношения many_many между классом Customer и классом Product. Например

Клиент БД

 | ID  | Name  |
-----------------------
| 01 | Jack   |
| 02 | Joe    |
| 03 | Claire |
  

DB Pruduct

 | ID  | ProductName |
---------------------------------
| 01 | watch        |
| 02 | pen          |
| 03 | car          |
  

Итак, после разработки / сборки я получаю новую таблицу БД с именем Customer_Products, в которой указаны идентификаторы обоих классов.
Допустим, клиенты добавили некоторые продукты, такие как следующие
DB Customer_Products

 | ID  | CutomerID | PruductID |
----------------------------------------------------
| 01 |  01        |  01       |    -> Jack added watch
| 02 |  02        |  01       |    -> Joe added watch
| 03 |  01        |  02       |    -> Jack added pen
| 04 |  01        |  03       |    -> Jack added car
| 05 |  03        |  01       |    -> Claire added watch
  

Теперь я хочу показать только клиентам, которые добавили часы, ручку и автомобиль (например).
Поэтому я хочу использовать запрос, чтобы показать только Джека, потому что он добавил 3 продукта. И вот моя проблема / вопрос.
Мой код:

 $sqlQuery = new SQLQuery();
$sqlQuery->setFrom("Customer"); 
$sqlQuery->addLeftJoin(' Customer_Products ','"Customer"."ID" = " Customer_Products "."CustomerID"');
$sqlQuery->addWhere("PruductID = 01  ");

// with this next two lines the result is empty, I know this is wrong but maybe this gives you an idea of what I m looking for. 
// $sqlQuery->addWhere("PruductID = 02 ");                  
// $sqlQuery->addWhere("PruductID = 03  ");     

$rawSQL = $sqlQuery->sql();
$rec = $sqlQuery->execute();
  

Есть ли способ сделать это с помощью одного запроса? Или как я мог это сделать? Спасибо за помощь!

Ответ №1:

Существует несколько подходов. Мне нравится group by having подход and, потому что он наиболее гибкий:

 select c.*
from customers c join
     customer_products cp
     on c.customerid = cp.customerid join
     products p
     on p.productid = cp.productid
where p.name in ('Pen', 'Car', 'Watch')
group by c.customerid
having sum(p.name = 'Pen') > 0 and
       sum(p.name = 'Car') > 0 and
       sum(p.name = 'Watch') > 0;
  

Каждое условие в having предложении проверяет наличие одного продукта. where Предложение является необязательным, но оно может повысить производительность.

Комментарии:

1. возможно ли таким образом использовать более 1 табличных соединений? Или я должен использовать WHERE вместо Group by и having?

2. @user3786012 . . . Я не понимаю вашего вопроса.

3. я имею в виду, когда я тоже должен проверить другую таблицу. например: есть также таблицы Adress, Настройки и многое другое. я хочу запросить следующее: покажите мне всех клиентов, которые добавили продукты 01, 02 И 03 И живут в Ardess. Город = ‘Лондон’ И имеют настройки.xyz = ‘x’ И так далее.

4. @user3786012 . . . Конечно. Условия могут поступать из любой из таблиц.