mysql选择与union all

时间:2013-11-27 20:05:40

标签: mysql union-all

我得到了

表A

| id | san | status |       created       |
-------------------------------------------
| 1  | 100 |   3    | 2013-11-01 19:26:20 |
| 2  | 200 |   8    | 2013-11-02 03:19:35 |
| 3  | 300 |   1    | 2013-11-03 06:13:38 |
| 4  | 100 |   2    | 2013-11-06 08:28:37 |
| 5  | 100 |   4    | 2013-11-27 19:00:00 |
| 6  | 200 |   1    | 2013-11-27 19:16:22 |
| 7  | 200 |   3    | 2013-11-27 19:33:33 |
| 8  | 300 |   5    | 2013-11-27 19:50:29 |

表B

| san | san-name |
------------------
| 100 |   xxx1   |
| 200 |   xxx2   |
| 300 |   xxx3   |

使用此查询(使用union all,因为我有大量行

SELECT id, max(lastdate) AS lastdate, max(san) AS san
FROM
    (SELECT `san` AS id,
            `created` AS lastdate,
            '' AS san
     FROM `TableA` a
     UNION ALL
     SELECT `san` AS id,
            cast(null as datetime) AS lastdate,
            `san-name` AS san
     FROM `TableB` b
    ) sq
GROUP BY id 
ORDER BY san ASC

我得到了这个结果(一切都很完美)

| id  |      lastdate       |   san   |
--------------------------------------
| 100 | 2013-11-27 19:00:00 |   xxx1  |
| 200 | 2013-11-27 19:33:33 |   xxx2  |
| 300 | 2013-11-27 19:50:29 |   xxx3  |


但现在我想添加"状态"最新的"创建" " ID"进入我的结果。


从TableA

我想要行(参见< -LATEST SAN .....)

| id | san | status |       created       |
-------------------------------------------
| 1  | 100 |   3    | 2013-11-01 19:26:20 |
| 2  | 200 |   8    | 2013-11-02 03:19:35 |
| 3  | 300 |   1    | 2013-11-03 06:13:38 |
| 4  | 100 |   2    | 2013-11-06 08:28:37 |
| 5  | 100 |   4    | 2013-11-27 19:00:00 | <- LATEST SAN 100
| 6  | 200 |   1    | 2013-11-27 19:16:22 |
| 7  | 200 |   3    | 2013-11-27 19:33:33 | <- LATEST SAN 200
| 8  | 300 |   5    | 2013-11-27 19:50:29 | <- LATEST SAN 300

它应该是这样的:

| id  | status |      lastdate       |   san   |
------------------------------------------------
| 100 |    4   | 2013-11-27 19:00:00 |   xxx1  |
| 200 |    3   | 2013-11-27 19:33:33 |   xxx2  |
| 300 |    5   | 2013-11-27 19:50:29 |   xxx3  |

我尝试使用此代码

SELECT id, status, max(lastdate) AS lastdate, max(san) AS san
FROM
    (SELECT `san` AS id,
            `created` AS lastdate,
            '' AS san,
            status AS status
     FROM `TableA` a
     UNION ALL
     SELECT `san` AS id,
            cast(null as datetime) AS lastdate,
            `san-name` AS san,
            '' AS status
     FROM `TableB` b
    ) sq
GROUP BY id 
ORDER BY san ASC

但它给了我(错误的结果)

| id  | status |      lastdate       |   san   |
------------------------------------------------
| 100 |    3   | 2013-11-27 19:00:00 |   xxx1  |
| 200 |    8   | 2013-11-27 19:33:33 |   xxx2  |
| 300 |    1   | 2013-11-27 19:50:29 |   xxx3  |

而不是像这样的正确

| id  | status |      lastdate       |   san   |
------------------------------------------------
| 100 |    4   | 2013-11-27 19:00:00 |   xxx1  |
| 200 |    3   | 2013-11-27 19:33:33 |   xxx2  |
| 300 |    5   | 2013-11-27 19:50:29 |   xxx3  |
有人能帮帮我吗? :O)

我创建了 sqlfiddle

最好的问候

bernte

1 个答案:

答案 0 :(得分:1)

我会尝试使用此查询:

SELECT tA.san AS id, tA.status, tA.created AS lastdate, tB.`san-name`
FROM
  tableA tA INNER JOIN (SELECT san, MAX(created) AS max_created
                        FROM tableA
                        GROUP BY san) m
  ON tA.san=m.san AND tA.created=m.max_created
  INNER JOIN tableB tB
  ON tA.san=tB.san

请参阅小提琴here

修改

如果你需要从tableB返回所有记录,只有与你匹配的记录需要使用RIGHT JOIN(这有点不常见),或者我们可以交换连接表的顺序并使用LEFT JOIN,如这样:

SELECT tB.san AS id, tA.status, tA.created AS lastdate, tB.`san-name`
FROM
  tableB tB LEFT JOIN
  (SELECT san, MAX(created) AS max_created
   FROM tableA
   GROUP BY san) m
  ON tB.san=m.san
  LEFT JOIN TableA tA
  ON tA.san=m.san AND tA.created=m.max_created

小提琴是here