У меня есть таблица под названием 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
Когда вы говорите «предыдущий», вы имеете в виду «есть неоплаченный заказ в таблице» или «заказ, представленный последней строкой». Если это последнее, вам нужно будет использовать оконные функции.
Ой, простите. OrderID уникален, моя ошибка.
Вы можете сделать агрегацию:
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;
Это будет сравниваться с более ранними заказами все, а не только с непосредственно предыдущим.
@ Бармар Это не проблема. Если у вас есть несколько оплаченных заказов и несколько предыдущих неоплаченных, то заказ, следующий за последним неоплаченным, оплачивается. Именно то, что просили. Я, наверное, не очень хорошо объясняю, но попробуй записать...
Понимаю. Поскольку вы используете DISTINCT
, дубликаты будут удалены. Но объединение будет более дорогим, потому что оно дает гораздо больший перекрестный продукт.
Поскольку в вашем вопросе конкретно указано, что «предыдущий заказ не оплачен», оконные функции должны быть здесь!
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"
Онлайн-демонстрация: Связь
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');
похоже, у вас есть несколько клиентов, связанных с одним и тем же идентификатором заказа. Могут ли несколько человек внести свой вклад в стоимость одного заказа? Это необычно, но возможно, я думаю. Просто хотел проверить, что означают данные?