获取每组MySql中的最后一项

时间:2016-07-01 23:38:38

标签: mysql sql

在第一张表中,我有订单。在第二个 - 发送到这些订单的消息。对于每个有active = 1的订单,我需要从最后一条消息中获取日期和状态(如果消息尚未发送,则为NULL)。表格由复合键连接 - “order_id + offer”。

“订单”表:

+----------+----------+--------+----------+
| order_id | offer    | active | timezone |
+----------+----------+--------+----------+
|        6 | kopiya   |      1 |        0 |
|        6 | kopiya-3 |      1 |        0 |
|       10 | kopiya   |      1 |      180 |
|       23 | kopiya-2 |      1 |        0 |
|       27 | kopiya-2 |      0 |        0 |
+----------+----------+--------+----------+

“短信”表:

+------+----------+----------+------+--------+---------------------+
| key_ | order_id | offer    | type | status | date                |
+------+----------+----------+------+--------+---------------------+
| 1    |        6 | kopiya   | text |      1 | 2016-06-20 00:00:00 |
| 2    |        6 | kopiya-3 | text |      0 | 2016-06-21 00:00:00 |
| 3    |       10 | kopiya   | text |      0 | 2016-06-27 00:00:00 |
| 4    |       27 | kopiya-2 | text |      1 | 2016-06-21 00:00:00 |
| 6    |        6 | kopiya-3 | text |      1 | 2016-06-23 00:00:00 |
+------+----------+----------+------+--------+---------------------+

结果将是:

+----------+----------+---------------------+--------+
| order_id | offer    | last_date           | status |
+----------+----------+---------------------+--------+
|        6 | kopiya   | 2016-06-20 00:00:00 |      1 |
|        6 | kopiya-3 | 2016-06-23 00:00:00 |      1 |
|       10 | kopiya   | 2016-06-27 00:00:00 |      0 |
|       23 | kopiya-2 | NULL                |   NULL |
+----------+----------+---------------------+--------+

此查询无效:

SELECT o.order_id, o.offer, max(date) as last_date, status
FROM orders AS o
LEFT JOIN sms AS s
ON o.order_id=s.order_id AND o.offer=s.offer
WHERE `active` = 1
GROUP BY o.order_id, o.offer;

它显示:

+----------+----------+---------------------+--------+
| order_id | offer    | last_date           | status |
+----------+----------+---------------------+--------+
|        6 | kopiya   | 2016-06-20 00:00:00 |      1 |
|        6 | kopiya-3 | 2016-06-23 00:00:00 |      0 |
|       10 | kopiya   | 2016-06-27 00:00:00 |      0 |
|       23 | kopiya-2 | NULL                |   NULL |
+----------+----------+---------------------+--------+

对于键“6 kopiya-3”,它返回状态= 0但是预期为1,因为它从第一行获得此值而不是具有最大日期的行。我该如何解决这个问题?

5 个答案:

答案 0 :(得分:1)

这与Unix One的答案是否相同,只是格式不同? 如果是这样,那么他们就会打败我 - 但请注意,这假设(order_id,offer)上的PK,并返回与请求的结果略有不同的结果集。

SELECT o.order_id
     , o.offer
     , s.date last_date
     , s.status
  FROM orders o 
  LEFT
  JOIN 
     ( SELECT x.* 
         FROM sms x
         JOIN 
            ( SELECT order_id
                   , offer
                   , MAX(date) date 
                FROM sms 
               GROUP 
                  BY order_id
                   , offer
            ) y 
           ON y.order_id = x.order_id 
          AND y.offer = x.offer
          AND y.date = x.date
      ) s
     ON s.order_id = o.order_id 
    AND s.offer = o.offer 
  WHERE o.active = 1;

答案 1 :(得分:0)

SELECT o.order_id, o.offer, max(date) as last_date, (select (SELECT sd.status FROM sms sd WHERE sd.order_id=o.order_id AND sd.offer=s.offer ORDER BY sd.key_ DESC LIMIT 1) as 'st' case when st = '1' then '1' else '0' end) as status
FROM orders AS o
LEFT JOIN sms AS s
ON o.order_id=s.order_id AND o.offer=s.offer
WHERE `active` = 1
GROUP BY o.order_id, o.offer;

如果我的语法正确可能会有效

旁注:我的答案很糟糕lol

答案 2 :(得分:0)

SELECT
  o.order_id,
  o.offer,
  s3.`date` AS last_date,
  s3.status
FROM
  orders o
  LEFT JOIN
    (SELECT
       s1.order_id,
       s1.offer
     FROM
       sms s1
       JOIN
         (SELECT
            MAX(key_) AS key_
          FROM
            sms
          GROUP BY
            order_id,
            offer) s2 ON s1.key_ = s2.key_) s3 ON (o.order_id = s3.order_id AND o.offer = s3.offer)

答案 3 :(得分:0)

Bingo,问题出在GROUP BY

的位置
SELECT o.order_id, o.offer, max(date) as last_date, status
FROM orders AS o
LEFT JOIN sms AS s
ON o.order_id=s.order_id AND o.offer=s.offer
WHERE `active` = 1
GROUP BY o.order_id, o.offer;

这导致以下结果:

WITH C AS (SELECT --columns
FROM Orders AS A
WHERE O.Active = 1
GROUP BY O.Order_ID, O.Offer)

SELECT --columns
FROM C
INNER JOIN sms AS S ON O.Order_ID = S.order_ID
                   AND O.Offer = S.Offer;

由于group by不是确定性的,因此您会收到错误。 相反,尝试这样的事情:

SELECT B.ORDER_ID, A.OFFER, B.Status, B.DATE
FROM Orders A
INNER JOIN (SELECT Order_ID, Offer, MAX([DATE]) AS [DATE], MAX(Status) AS [Status]
            FROM #EXAMPLE2
            GROUP BY Order_ID, OFFER) B ON A.Offer = B.OFFER 
                                   AND A.Order_ID = B.Order_ID
WHERE ACTIVE = 1;

Results:
-- 6    kopiya      1       2016-06-20 00:00:00.000
-- 27   kopiya-2    1       2016-06-21 00:00:00.000
-- 6    kopiya-3    1       2016-06-23 00:00:00.000
-- 23   kopiya-2    NULL    NULL

现在,您的Orders表上的谓词会执行它应该执行的操作,并过滤结果。

答案 4 :(得分:0)

我认为这可以满足您的需求:

select sms.*
from orders o left join
     sms
     on o.order_id = sms.order_id and o.offer = sms.offer
where sms.date = (select max(sms2.date)
                  from sms sms2
                  where sms2.order_id = sms.order_id and sms2.offer = sms.offer
                 ) or
      sms.order_id is null

对于此查询,我建议sms(order_id, offer, date)上的索引。