在 PostgreSQL 中:我有一个包含 3 列的表:
CustomerNum, OrderNum, OrderDate
.
每个日期范围内每个客户可能有(也可能没有)很多订单。我需要的是位于提供的日期范围内的每个客户的最后一个 OrderNum。我一直在做的是获取客户的 ResultSet 并分别查询每个客户,但这需要太多时间。
有没有办法使用子选择来选择客户,然后为每个客户获取最后一个 OrderNum?
在 PostgreSQL 中:我有一个包含 3 列的表:
CustomerNum, OrderNum, OrderDate
.
每个日期范围内每个客户可能有(也可能没有)很多订单。我需要的是位于提供的日期范围内的每个客户的最后一个 OrderNum。我一直在做的是获取客户的 ResultSet 并分别查询每个客户,但这需要太多时间。
有没有办法使用子选择来选择客户,然后为每个客户获取最后一个 OrderNum?
在 postgres 上,您还可以使用非标准DISTINCT ON
子句:
SELECT DISTINCT ON (CustomerNum) CustomerNum, OrderNum, OrderDate
FROM Orders
WHERE OrderDate BETWEEN 'yesterday' AND 'today'
ORDER BY CustomerNum, OrderDate DESC;
请参阅http://www.postgresql.org/docs/current/static/sql-select.html#SQL-DISTINCT
select customernum, max(ordernum)
from table
where orderdate between '...' and '...'
group by customernum
就这样。
SELECT t1.CustomerNum, t1.OrderNum As LastOrderNum, t1.LastOrderDate
FROM table1 As t1
WHERE t1.OrderDate = (SELECT MAX(t2.OrderDate)
FROM table1 t2
WHERE t1.CustomerNum = t2.CustomerNum
AND t2.OrderDate BETWEEN date1 AND date2)
AND t1.OrderDate BETWEEN date1 AND date2
不确定您的 Customer 表的结构或关系,但这应该有效:
SELECT Customer.Num, (
SELECT OrderNum FROM Orders WHERE CustomerNum = Customer.Num AND OrderDate BETWEEN :start AND :end ORDER BY OrderNum DESC LIMIT 1
) AS LastOrderNum
FROM Customer
-- generate some data
DROP TABLE tmp.orders;
CREATE TABLE tmp.orders
( id INTEGER NOT NULL
, odate DATE NOT NULL
, payload VARCHAR
)
;
ALTER TABLE tmp.orders ADD PRIMARY KEY (id,odate);
INSERT INTO tmp.orders(id,odate,payload) VALUES
(1, '2011-10-04' , 'one' )
, (1, '2011-10-24' , 'two' )
, (1, '2011-10-25' , 'three' )
, (1, '2011-10-26' , 'four' )
, (2, '2011-10-23' , 'five' )
, (2, '2011-10-24' , 'six' )
;
-- CTE to the rescue ...
WITH sel AS (
SELECT * FROM tmp.orders
WHERE odate BETWEEN '2011-10-23' AND '2011-10-24'
)
SELECT * FROM sel s0
WHERE NOT EXISTS (
SELECT * FROM sel sx
WHERE sx.id = s0.id
AND sx.odate > s0.odate
)
;
结果:
DROP TABLE
CREATE TABLE
NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "orders_pkey" for table "orders"
ALTER TABLE
INSERT 0 6
id | odate | payload
----+------------+---------
1 | 2011-10-24 | two
2 | 2011-10-24 | six
(2 rows)
如果最后一个订单号是指最大的订单号,那么您可以将您的选择用作客户编号的谓词,对结果进行分组并选择最大值:
SELECT CustomerNum, MAX(OrderNum) AS LastOrderNum
FROM Orders
WHERE
CustomerNum IN (SELECT CustomerNum FROM ...)
AND
OrderDate BETWEEN :first_date AND :last_date
GROUP BY CustomerNum
如果最后一个订单号不一定是最大的订单号,那么您需要找到每个客户的最大订单日期并将其与其余订单连接起来以找到相应的编号:
SELECT O.CustomerNum, O.OrderNum AS LastOrderNum
FROM
(SELECT CustomerNum, MAX(OrderDate) AS OrderDate
FROM Orders
WHERE
OrderDate BETWEEN :first_date AND :last_date
AND
CustomerNum IN (SELECT CustomerNum FROM ...)
GROUP BY CustomerNum
) AS CustLatest
INNER JOIN
Orders AS O USING (CustomerNum, OrderDate);