MySQL выбирает дублирующиеся платежные отложенные заказы без соответствующего оплаченного заказа - PullRequest
0 голосов
/ 02 января 2019

Структура моей таблицы:

заказов

+------+-------------+----------------+-------------+
| id   | customer_id | payment_status |   created_on| 
+------+-------------+----------------+-------------+
| 1    |      1      |      unpaid    | 2018-12-28  |
| 2    |      1      |      unpaid    | 2018-12-29  |
| 3    |      2      |      unpaid    | 2018-12-29  |
| 4    |      2      |      unpaid    | 2018-12-29  |
| 5    |      4      |      paid      | 2018-12-30  |
| 6    |      3      |      unpaid    | 2018-12-30  |
+------+-------------+----------------+-------------+

order_items

+------+-----------+-------------+----------+-------+
| id   | order_id  |  product_id | quantity | price |
+------+-----------+-------------+----------+-------+
| 1    |   1       |      4      |  2       | 20.50 |
| 2    |   1       |      5      |  2       | 25.00 |
| 3    |   2       |      4      |  2       | 20.50 |
| 4    |   2       |      5      |  2       | 25.00 |
| 5    |   3       |      1      |  1       | 20.00 |
| 6    |   3       |      2      |  1       | 25.00 |
| 7    |   4       |      1      |  1       | 20.00 |
| 8    |   4       |      2      |  1       | 25.00 |
| 9    |   5       |      4      |  2       | 20.50 |
| 10   |   5       |      5      |  2       | 25.00 |
| 11   |   6       |      3      |  4       | 15.00 |
+------+-----------+-------------+----------+-------+

customer

+-----+---------------+----------+
| id  | email         |  name    |
+-----+---------------+----------+
| 1   | abc@mail.com  |  user 1  |
| 2   | xyz@mail.com  |  user 2  |
| 3   | pqr@mail.com  |  user 3  |
| 4   | abc@mail.com  |  user 4  |
+-----+---------------+----------+

Q: Я хочу данныекак заказы, отправленные по одному электронному письму клиента с ожидающим статусом и без заказов с оплаченным статусом этого клиента в течение недели

Ожидаемый результат: 1 разовый заказ без соответствующего оплаченного заказа в течение недели

+------+-------------+----------------+-------------+
| id   | customer_id | payment_status |   created_on| 
+------+-------------+----------------+-------------+
| 3    |      2      |      unpaid    | 2018-12-29  |
| 4    |      2      |      unpaid    | 2018-12-29  |
| 6    |      3      |      unpaid    | 2018-12-30  |
+------+-------------+----------------+-------------+

В: Мне нужны данные, как если бы в одном электронном письме клиента было 2 заказа с одинаковыми продуктами и одинаковым количеством с ожидающим статусом и без заказов с оплаченным статусом у этого клиента в течение недели

Ожидаемый результат:2 два заказа без соответствующего оплаченного заказа в течение недели

+------+-------------+----------------+-------------+
| id   | customer_id | payment_status |   created_on| 
+------+-------------+----------------+-------------+
| 3    |      2      |      unpaid    | 2018-12-29  |
| 4    |      2      |      unpaid    | 2018-12-29  |
+------+-------------+----------------+-------------+

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 08 января 2019

Я полностью согласен с Риком по поводу очистки схемы

Если я правильно вас прочитал, в настоящее время ваша таблица customer фактически просто добавляет столбцы email и name к вашему ordersтаблица


Q1

Если вы хотите, чтобы в течение недели с сегодняшней даты поля идентификатора не могли быть пустыми

SELECT ou.*
  FROM orders ou /** orders unpaid */
  JOIN customer cu /** customer unpaid */
    ON cu.id = ou.customer_id
 WHERE ou.payment_status = 'unpaid'
   AND NOT EXISTS (
     SELECT 1 
       FROM orders op /** orders paid */
       JOIN customer cp /** customer paid */
         ON cp.id = op.customer_id
      WHERE op.payment_status = 'paid'
        AND op.created_on > CURDATE() - INTERVAL 1 WEEK /** or >= if required */
        AND cp.email = cu.email 
   )

NB Поскольку с момента оплаченных заказов в ваших примерах прошло больше недели, вам придется отрегулировать временное условие, чтобы увидеть те же результаты


Q2

Те же предположения, что и в первом квартале, плюс предположение о том, что product_id может появляться только один раз за заказ

SELECT ou.*
  FROM orders ou /** orders unpaid */
  JOIN customer cu /** customer unpaid */
    ON cu.id = ou.customer_id
  JOIN (  
    SELECT GROUP_CONCAT(oudc.id) orders_csv
      FROM (
        SELECT oui.id,
               cui.email,
               GROUP_CONCAT(oiui.product_id ORDER BY oiui.product_id) products,
               GROUP_CONCAT(oiui.quantity ORDER BY oiui.product_id) quantity
          FROM orders oui /** orders unpaid internal */
          JOIN customer cui /** customer unpaid internal */
            ON cui.id = oui.customer_id
          JOIN order_items oiui /** order items unpaid internal */      
            ON oiui.order_id = oui.id
         WHERE oui.payment_status = 'unpaid'   
      GROUP BY oui.id,
               cui.email
           ) oudc /** orders unpaid dupe check */
  GROUP BY oudc.email, 
           oudc.products, 
           oudc.quantity
    HAVING COUNT(*) = 2 /** or >=2 if required */   
       ) oud /** orders unpaid dupes */
    ON FIND_IN_SET(ou.id, oud.orders_csv) > 0
 WHERE ou.payment_status = 'unpaid'
   AND NOT EXISTS (
     SELECT 1 
       FROM orders op /** orders paid */
       JOIN customer cp /** customer paid */
         ON cp.id = op.customer_id
      WHERE op.payment_status = 'paid'
        AND op.created_on > CURDATE() - INTERVAL 1 WEEK /** or >= if required */
        AND cp.email = cu.email 
   ) 

NB Поскольку с момента оплаты оплаченных заказов прошло более неделиВ ваших примерах вам нужно будет скорректировать временное условие, чтобы увидеть те же результаты

Этот запрос проверен только приблизительно и, вероятно, очень медленный.Я предлагаю вам выполнить каждый вложенный запрос выбора по отдельности (начиная с самого глубокого), чтобы увидеть, что происходит.По сути, он объединяет заказы в 1 строку каждый, затем объединяет дубликаты заказов с одним и тем же адресом электронной почты в 1 строку каждый, а затем проверяет наличие заказов в этой строке, используя логику, аналогичную Q1

Если вы можете иметь одинаковые product_id более одного раза за заказ, вы можете нормализовать с помощью дополнительной вложенной группировки, выбранной в моем orders unpaid dupe check подзапросе


SQLfiddle

У меня также создал SQLfiddle , чтобы продемонстрировать эти 2 запроса в действии на данных вашего примера.Однако я настроил даты примеров заказов, чтобы они зависели от текущей даты

0 голосов
/ 06 января 2019

Первый запрос сомнителен - Вы действительно имели в виду email или customer_id?Последний должен быть таким, каким вы разработали схему, чтобы отличить одного «клиента» от другого.Подумай об этом.(И исправьте данные, чтобы сделать их понятными.) Между тем я предположу, что customer_id различает клиентов.

Я не могу обернуться вокруг цели первого запроса.Вы ищете клиентов, которые оплатили более поздний заказ, но не оплатили более ранний заказ?Или ищете неправильные сообщения в базе данных?Во всяком случае, здесь есть выстрел:

SELECT  Unpd.id, Unpd.customer_id, Unpd.payment_status, Unpd.created_on
    FROM  Orders AS Pd  ON Pd.customer_id = C.id
      AND  payment_status = 'paid'
    WHERE  NOT EXISTS 
    (
        SELECT  1
            FROM  Orders AS Pd
            WHERE  Pd.customer_id = C.id
              AND  Pd.payment_status = 'paid'
              AND  Pd.created_on > NOW() - INTERVAL 1 WEEK 
    ) 

Второй запрос.Я перефразирую его следующим образом: Найдите два (или более) заказа (оплаченных или неоплаченных) одним и тем же клиентом в один и тот же день (но не проверяя, совпадают ли позиции):

SELECT  O2.id, O2.customer_id, O2.payment_status, O2.created_on
    FROM  
    (
        SELECT  O.customer_id, O.created_on
            FROM  Orders AS O
            GROUP BY  O.customer_id, O.created_on
            HAVING  COUNT(*) >= 2
    ) AS MultipleInOneDay
    JOIN  Orders AS O2  USING (customer_id, created_on)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...