Получить все повторяющиеся именованные клиенты на основе другого значения таблиц

#sql

Вопрос:

У меня есть следующие 4 таблицы:

Клиенты:

  ---- ------------ ----------- 
| id | first_name | last_name |....
 ---- ------------ ----------- 
|  1 | bob        | dylan     |
|  2 | alice      | brown     |
|  3 | liv        | green     |
|  4 | bob        | dylan     |
 ---- ------------ ----------- 
 

Заказы:

  ---- ------------- 
| id | customer_id |....
 ---- ------------- 
|  1 |           1 |
|  2 |           2 |
|  3 |           3 |
|  4 |           4 |
 ---- ------------- 
 

Элемент заказа:

 
 ---- ----------- ---------- 
| id | order_id  | fruit_id |....
 ---- ----------- ---------- 
|  1 |         1 |        1 |
|  2 |         2 |        2 |
|  3 |         3 |        3 |
|  4 |         4 |        4 |
 ---- ----------- ---------- 
 

Фрукты:

 
 ---- -------------- 
| id | taste_rating | .....
 ---- -------------- 
|  1 |            5 |
|  2 |            5 |
|  3 |            2 |
|  4 |            5 |
 ---- -------------- 
 

Я пытаюсь привлечь всех пользователей, которые разделяют то же first_name самое и last_name которые заказали фрукты ТОЛЬКО с taste_rating 5

Пример вывода на основе приведенных выше таблиц:

 
 ------- ------- ------------ ----------- 
| u1_id | u2_id | first_name | last_name |
 ------- ------- ------------ ----------- 
|     1 |     4 | bob        | dylan     |
 ------- ------- ------------ ----------- 
 

Это потому, что внутри customers есть 2 «Боба Дилана», когда, соединяя их с orders помощью, мы получаем 2 идентификатора 1 amp; 4 , а затем, соединяя их с order_item помощью , мы получаем fruit_id 1 amp; 4 . Наконец, когда мы получаем плоды из fruit_id , мы видим, что id из обоих 1 и 4 имеют taste_rating из 5.

Я попробовал выполнить следующий запрос:

 SELECT customers.id, customers.first_name, customers.last_name
FROM customers 
INNER JOIN orders ON orders.customer_id = customers.id
INNER JOIN order_item ON order_item.order_id = orders.id
INNER JOIN fruits ON fruits.id = order_item.fruits_id
WHERE fruits.id IN (
        SELECT fruits.id
        FROM fruits
        GROUP BY fruits.id
        HAVING taste_rating = 5)
GROUP BY customers.first_name, customers.last_name, customers.id, fruits.taste_rating
 

Это дает мне всех пользователей, у которых были заказы только с помощью a taste_rating = 5 , хотя я не уверен, как получить только тех, у кого такие же first_name amp; last_name

Ответ №1:

Когда вы не группируете по customers.id .
Тогда количество уникальных идентификаторов клиентов не будет равно 1 для клиентов, у которых более 1 идентификатора.
(или разные люди с одним и тем же именем)

Поскольку они заказали только 5 оценок, некоторые проверки условного агрегирования могут помочь в этом.

 SELECT 
  MIN(cust.id) AS u1_id
, MAX(cust.id) AS u2_id
, cust.first_name
, cust.last_name
--, COUNT(DISTINCT cust.id) AS TotalUniqCustId
--, COUNT(DISTINCT fruit.id) AS TotalFruitId
--, MAX(CASE WHEN fruit.taste_rating != 5 THEN 1 ELSE 0 END) AS HadBeside5
--, COUNT(DISTINCT CASE WHEN fruit.taste_rating = 5 THEN cust.id END) AS TotalCustHad5
FROM customers AS cust
INNER JOIN orders ON orders.customer_id = cust.id
INNER JOIN order_item AS itm ON itm.order_id = orders.id
LEFT JOIN fruits AS fruit ON fruit.id = itm.fruit_id
GROUP BY cust.first_name, cust.last_name
HAVING COUNT(DISTINCT cust.id) >= 2 -- same name users
   AND MAX(CASE WHEN fruit.taste_rating != 5 THEN 1 ELSE 0 END) = 0
   AND COUNT(DISTINCT CASE WHEN fruit.taste_rating = 5 THEN cust.id END) >= 2
;
 
u1_id u2_id first_name last_name
1 4 боб дилан

db<>скрипка здесь

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

1. Это дает мне всех пользователей, у которых есть хотя бы один рейтинг 5 , а не КАЖДЫЙ рейтинг 5 . Это также не дает мне идентификаторы пользователей двух пользователей с одинаковыми именами.

2. @bobdylan01 Проверьте обновление. Теперь со скрипкой.

3. Это все еще не дает мне id клиентов, у которых одно и то же имя. Пример выходной таблицы в моем вопросе — это то, как должен выглядеть результат. Меня не волнуют итоги

4. Хорошо, теперь с идентификаторами и без итогов.