我想找到针对哪个指定NULL
的上次付款(或product_id
,如果n / a)。下面是我正在使用的表格(简化版)的表示。
+----------+
|Products |
|----------+
|product_id|
+----------+
+---------------+
|Orders |
+---------------+
|order_id |
|order_timestamp|
|order_status |
+---------------+
+-----------------+
|ProductsOrdersMap|
+-----------------+
|product_id |
|order_id |
+-----------------+
在JOINs,MAXs,GROUP BYs,LEFT JOINs,多个INNER JOINs以获得最大n-group-group之后,我仍然无法获得正确的结果。大多数情况下,具有多个订单的产品会返回多行。到目前为止我得到的最好结果是(我正在搜索特定产品):
product_id order_id order_timestamp order_status
8 NULL NULL NULL
9 NULL NULL NULL
10 NULL NULL NULL
12 NULL NULL NULL
13 NULL NULL NULL
14 11 2013-08-13 07:22:01 finished
15 11 2013-08-13 07:22:01 finished
15 12 2013-08-14 00:00:00 finished
32 11 2013-08-13 07:22:01 finished
83 9 2013-08-13 07:04:02 finished
83 10 2013-08-13 07:11:42 finished
编辑: PP之后。 anwser,我最终得到了以下查询:
SELECT p.product_id, o.order_id, MAX(order_timestamp) AS order_timestamp, order_status
FROM Products p LEFT JOIN (ProductsOrdersMap m, Orders o)
ON (p.product_id = m.product_id AND m.order_id = o.order_id)
WHERE p.product_id IN (8,9,10,12,13,14,15,32,83)
GROUP BY p.product_id
返回
product_id order_id order_timestamp order_status
8 NULL NULL NULL
9 NULL NULL NULL
10 NULL NULL NULL
12 NULL NULL NULL
13 NULL NULL NULL
14 11 2013-08-13 07:22:01 finished
15 11 2013-08-13 07:22:01 finished
32 11 2013-08-13 07:22:01 finished
83 9 2013-08-13 07:04:02 finished
乍一看,它似乎是正确的,但只有产品ID和时间戳是正确的。比较上面的两个查询,您可以看到,对于产品15和83,order_id
是错误的(order_status
也可能是错误的。)
答案 0 :(得分:2)
此查询应返回指定的结果集(这只是桌面检查,未经测试)
返回所有product_id
SELECT p.product_id
, m.order_d
, m.order_timestamp
, m.order_status
FROM products p
LEFT
JOIN ( SELECT kl.product_id
, MAX(ko.order_timestamp) AS latest_timestamp
FROM orderproductsmap kl
JOIN orders ko
ON ko.order_id = kl.order_id
GROUP
BY kl.product_id
) l
ON l.product_id = p.product_id
LEFT
JOIN ( SELECT ml.product_id
, mo.order_id
, mo.order_timestamp
, mo.order_status
FROM orderproductsmap ml
JOIN orders mo
ON mo.order_id = ml.order_id
) m
ON m.product_id = l.product_id
AND m.order_timestamp = l.latest_timestamp
GROUP
BY p.product_id
内嵌视图“l
”会为每个“order_timestamp
”获取最新的“product_id
”。这与内联视图“m
”相结合,以获取具有最新时间戳的订单的整行。
如果恰好有多个订单使用相同的最新“order_timestamp
”(即order_timestamp
不能保证对于给定的product_id
是唯一的),那么最外面的GROUP BY
1}}确保只返回其中一个订单行。
如果只需要返回特定的product_id值,请在最外层的查询中添加WHERE子句。为了提高性能,可以在内联视图中重复相同的谓词。
只返回SPECIFIC product_id 我们添加了三个WHERE子句:
SELECT p.product_id
, m.order_d
, m.order_timestamp
, m.order_status
FROM products p
LEFT
JOIN ( SELECT kl.product_id
, MAX(ko.order_timestamp) AS latest_timestamp
FROM orderproductsmap kl
JOIN orders ko
ON ko.order_id = kl.order_id
WHERE kl.product_id IN (8,9,10,12,13,14,15,32,83)
GROUP
BY kl.product_id
) l
ON l.product_id = p.product_id
LEFT
JOIN ( SELECT ml.product_id
, mo.order_id
, mo.order_timestamp
, mo.order_status
FROM orderproductsmap ml
JOIN orders mo
ON mo.order_id = ml.order_id
WHERE ml.product_id IN (8,9,10,12,13,14,15,32,83)
) m
ON m.product_id = l.product_id
AND m.order_timestamp = l.latest_timestamp
WHERE p.product_id IN (8,9,10,12,13,14,15,32,83)
GROUP
BY p.product_id
只需要最外层查询的WHERE子句。添加另外两个只是为了通过限制每个派生表的大小来提高性能。
答案 1 :(得分:1)
SELECT
P.product_id
,MAX(order_timestamp)
FROM
Products P
,Orders O
,ProductsOrdersMap M
WHERE
P.product_id = M.product_id
AND O.order_id = M.order_id
GROUP BY
P.product_id
答案 2 :(得分:1)
要退回所有产品,即使是那些没有订单的产品,LEFT JOIN
肯定是要走的路。 @PP上面的答案使用“旧式”内连接,相当于:
SELECT
P.product_id
,MAX(order_timestamp)
FROM Products P
INNER JOIN ProductsOrdersMap M ON P.product_id = M.product_id
INNER JOIN Orders O ON O.order_id = M.order_id
GROUP BY
P.product_id
从这个语法开始,访问LEFT JOIN
要容易得多 - 只需用INNER
替换LEFT
:
SELECT
P.product_id
,MAX(order_timestamp)
FROM Products P
LEFT JOIN ProductsOrdersMap M ON P.product_id = M.product_id
LEFT JOIN Orders O ON O.order_id = M.order_id
GROUP BY
P.product_id
附录:Renato需要的不仅仅是将其他答案重新设为LEFT JOIN
,因为order_id
和order_status
必须附带最大时间戳。最简单的方法是从产品ID列表和订单ID开始,订单的最大时间戳为order_id
:
SELECT
p2.product_id,
o2.order_id
FROM Products p2
INNER JOIN ProductsOrdersMap m ON p2.product_id = m.product_id
INNER JOIN Orders o2 ON m.order_id = o2.order_id
WHERE (o2.order_id, o2.order_timestamp) IN (
SELECT order_id, MAX(order_timestamp)
FROM Orders
GROUP BY order_id)
然后,不使用ProductsOrdersMap
将产品解析为订单,而是使用上述查询中的结果:
SELECT
p.product_id,
o.order_id,
o.TS,
o.order_status
FROM Products p
LEFT JOIN (
SELECT
p2.product_id,
o2.order_id
FROM Products p2
INNER JOIN ProductsOrdersMap m ON p2.product_id = m.product_id
INNER JOIN Orders o2 ON m.order_id = o2.order_id
WHERE (o2.order_id, o2.order_timestamp) IN (
SELECT order_id, MAX(order_timestamp)
FROM Orders
GROUP BY order_id)
) MaxTS ON p.product_id = MaxTS.product_id
LEFT JOIN Orders o ON MaxTS.order_id = o.order_id