Как сравнить значение из следующей строки?

У меня есть таблица под названием Order

   OrderID        CustomerID        IsPaid  
--------------------------------------------
    1              12                 no      
    2              12                 yes
    3              13                 no      
    4              13                 no
    5              14                 yes      
    6              14                 yes

и у меня есть таблица с именем Customer

   CustomerID      Cust_name    
--------------------------------
    12              John                       
    13              Nick                 
    14              Paul                                   

Мне нужно отобразить тех клиентов, которые оплатил заказ, но не оплатил предыдущий заказ, поэтому результат должен быть

   CustomerID      Cust_name    
--------------------------------
    12              John 

похоже, у вас есть несколько клиентов, связанных с одним и тем же идентификатором заказа. Могут ли несколько человек внести свой вклад в стоимость одного заказа? Это необычно, но возможно, я думаю. Просто хотел проверить, что означают данные?

ADyson 10.04.2019 18:14

Когда вы говорите «предыдущий», вы имеете в виду «есть неоплаченный заказ в таблице» или «заказ, представленный последней строкой». Если это последнее, вам нужно будет использовать оконные функции.

Nathaniel Pisarski 10.04.2019 18:15

Ой, простите. OrderID уникален, моя ошибка.

Jora 10.04.2019 19:05
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
2
3
60
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вы можете сделать агрегацию:

select c.CustomerID, c.Cust_name
from Customer c inner join
     Order o
     on o.CustomerID = c.CustomerID
group by c.CustomerID, c.Cust_name   
having min(o.IsPaid) <> max(o.IsPaid);

таким образом вы получите результат, только если он существует

SELECT *
FROM   customer
       INNER JOIN order
               ON customer.customerid = order.customerid
WHERE  ispaid = 'yes';  
Ответ принят как подходящий

Вы можете попробовать это:

SELECT   DISTINCT
         cust.CustomerID,
         cust.Cust_name
FROM     customer cust
JOIN     order    paid
  ON     cust.CustomerID = paid.CustomerID
 AND     paid.IsPaid = 'yes'
JOIN     order    unpd
  ON     cust.CustomerID = unpd.CustomerID
 AND     unpd.IsPaid = 'no'
 AND     unpd.OrderID < paid.OrderID
ORDER BY cust.CustomerID,
         cust.Cust_name;

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

SELECT   DISTINCT
         cust.CustomerID,
         cust.Cust_name
FROM     customer cust
JOIN     order    paid
  ON     cust.CustomerID = paid.CustomerID
 AND     paid.IsPaid = 'yes'
WHERE    EXISTS (SELECT *
                 FROM   order unpd
                 WHERE  cust.CustomerID = unpd.CustomerID
                   AND  unpd.IsPaid = 'no'
                   AND  unpd.OrderID < paid.OrderID)
ORDER BY cust.CustomerID,
         cust.Cust_name;

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

Barmar 10.04.2019 18:32

@ Бармар Это не проблема. Если у вас есть несколько оплаченных заказов и несколько предыдущих неоплаченных, то заказ, следующий за последним неоплаченным, оплачивается. Именно то, что просили. Я, наверное, не очень хорошо объясняю, но попробуй записать...

Robert Kock 10.04.2019 18:38

Понимаю. Поскольку вы используете DISTINCT, дубликаты будут удалены. Но объединение будет более дорогим, потому что оно дает гораздо больший перекрестный продукт.

Barmar 10.04.2019 18:42

Поскольку в вашем вопросе конкретно указано, что «предыдущий заказ не оплачен», оконные функции должны быть здесь!

SELECT *
FROM
(
    SELECT *,
           LAG(IsPaid) OVER (PARTITION BY CustomerID ORDER BY OrderId) AS IsPreviousOrderPaid
    FROM #Orders AS o
) ordersWithPrevious
    INNER JOIN #Customer AS c
        ON c.CustomerId = ordersWithPrevious.CustomerID
WHERE ordersWithPrevious.IsPaid = 1
      AND ordersWithPrevious.IsPreviousOrderPaid = 0;

Вы могли бы сделать что-то вроде этого..

SELECT t1.customerid,
       Max(cust_name) AS cust_name
FROM   table1 t1
       INNER JOIN table2 t2 using (customerid)
GROUP  BY t1.customerid
HAVING Group_concat(ispaid) = "no,yes"  

Онлайн-демонстрация: Связь


Table Structure and Sample data
CREATE TABLE Table1(
    OrderID int,
    CustomerID int,
    IsPaid varchar(03)
);

CREATE TABLE Table2(
    CustomerID int,
    Cust_name varchar(255)
);

INSERT INTO Table1
VALUES 
(1, 12, 'no'),
(2, 12, 'yes'),
(3, 13, 'no'),
(4, 13, 'no'),
(1, 14, 'yes'),
(2, 14, 'yes');

INSERT INTO Table2
VALUES  
(12, 'John'),
(13, 'Nick'),
(14, 'Paul');

Другие вопросы по теме