【问题标题】:Get result from joined tables从连接的表中获取结果
【发布时间】:2019-09-15 01:24:44
【问题描述】:

我有 2 张桌子:

表 1:

| jobid | jobname |
|     1 | job a   |
|     2 | job b   |

表 2:

| id | jobid | statusid | statusdate          | desc   |
|  1 |     1 |      100 | 2019.04.25 10:00:00 | first  |
|  2 |     2 |      100 | 2019.04.25 11:00:00 | first  |
|  3 |     2 |      100 | 2019.04.25 12:00:00 | second |

table2 中的作业可以有多个相同的“statusid”,但不同的“statusdate”和“desc”

我需要像这样获取最后一个“statusid”= 100 的工作列表:

| 1 | job a | 1 | 1 | 100 | 2019.04.25 10:00:00 | first  |
| 2 | job b | 3 | 2 | 100 | 2019.04.25 12:00:00 | second |
SELECT * FROM table1
INNER JOIN table2 ON table1.id = table2.jobid
GROUP BY table1.id

此查询返回错误结果,例如:

| 1 | job a | 1 | 1 |   | 100 | 2019.04.25 10:00:00 | first |
| 2 | job b | 3 | 2 | 2 | 100 | 2019.04.25 11:00:00 | first |

【问题讨论】:

  • "此查询返回错误结果,如:" 是的,这是因为 "SQL-92 及更早版本不允许选择列表、HAVING 条件或ORDER BY 列表指的是未在 GROUP BY 子句中命名的非聚合列。” 请参阅 manual .. 所以你的 SQL SELECT * .. GROUP BY table1.id 很可能是无效的 SQL,除非 MySQL 可以使用 functionally dependent 来获得正确的不在分组依据中的每个选定列的数据
  • 但 MySQL 总是扩展 GROUP BY 功能并允许无效的 GROUP BY 查询,代价是对于未在 GROUP BY 中命名的每个选定列的无效(与组无关)数据
  • 应该如何处理领带,这会发生什么?
  • 谢谢,对于答案,我会阅读手册。我每个工作只需要 1 条记录
  • “我每个工作只需要 1 条记录” 是的,是哪一个?我假设这些表有带有 AUTO_INCREMENT 选项的列,如果两个 statusdate 相同,我们可以使用它来排序获取最后一条记录?

标签: mysql mariadb groupwise-maximum


【解决方案1】:

您应该能够通过执行以下操作来实现:

表格

drop table if exists table1;
create table table1 (jobid int, jobname char(10));
insert into table1 values (1, 'job a'), (2, 'job b');

drop table if exists table2;
create table table2 (
    id int,
    jobid int,
    statusid int,
    statusdate timestamp,
    `desc` char(10)
);
insert into table2 values
(1,1,100,'2019.04.25 10:00:00','first')
,(2,2,100,'2019.04.25 11:00:00','first')
,(3,2,100,'2019.04.25 12:00:00','second');

查询

select
    t1.*,
    t2.*
from table1 t1
inner join (
    select jobid, max(statusdate) as maxstatusdate
    from table2
    group by jobid
) tn on t1.jobid = tn.jobid
inner join table2 t2 on tn.jobid = t2.jobid and tn.maxstatusdate = t2.statusdate;

结果

jobid   jobname id  jobid   statusid    statusdate          desc
1       job a   1   1       100         25.04.2019 10:00:00 first
2       job b   3   2       100         25.04.2019 12:00:00 second

说明

  • 对于每个作业 ID,查找最大状态日期
  • 将其加入 table1 以从 table1 获取信息。公共字段是jobid
  • 将他们的结果加入到 table2 中,其中包含您想要的所有剩余信息。常用字段是 jobid 和 statusdate。由于我们将 max status date 别名为不同的名称,因此请确保我们在连接中使用了正确的名称

示例:https://rextester.com/HRSWZ89705

【讨论】:

  • topicstarter 记住这不能处理ties
  • Topicstarter 也 "我需要获取最后一个 "statusid" = 100" 的工作列表 这个 qeury 不会检查,请记住这一点,this 一个
  • 关系:好的,我可以获得 max(table2.id) WHERE table2.statusid='100'
  • @lemlem 是的,您可以修改子查询的选择以读取select jobid, max(id) as maxid 并将与 t2 的连接更改为读取tn.maxid = t2.id
  • @RaymondNijland 我认为 lem lem 打算最大化,所以我在评论中建议需要更改哪些行。我没有更改我的答案或 rextester 链接,因为我在等着看 lem lem 在规范中的位置。
【解决方案2】:
DROP TABLE IF EXISTS table1;

CREATE TABLE table1
(jobid INT NOT NULL PRIMARY KEY
,jobname VARCHAR(12) UNIQUE
);

INSERT INTO table1 VALUES
(1,'job a'),
(2,'job b'),
(3,'job c');

DROP TABLE IF EXISTS table2;

CREATE TABLE table2
(id SERIAL PRIMARY KEY
,jobid INT NOT NULL
,statusid INT NOT NULL
,statusdate DATETIME NOT NULL
,description VARCHAR(12) NOT NULL
);

INSERT INTO table2 VALUES
(1,1,100,'2019-04-25 10:00:00','first'),
(2,2,100,'2019-04-25 11:00:00','first'),
(3,2,100,'2019-04-25 12:00:00','second');

SELECT a.*
     , b.id x_id
     , b.statusid
     , b.statusdate
     , b.description 
  FROM table1 a 
  LEFT 
  JOIN 
     ( SELECT x.* 
         FROM table2 x
         JOIN 
            ( SELECT MAX(id) id 
                FROM table2 
               WHERE statusid = 100 
               GROUP 
                  BY jobid
            ) y 
           ON y.id = x.id
     ) b
    ON b.jobid = a.jobid 
;


+-------+---------+------+----------+---------------------+-------------+
| jobid | jobname | x_id | statusid | statusdate          | description |
+-------+---------+------+----------+---------------------+-------------+
|     1 | job a   |    1 |      100 | 2019-04-25 10:00:00 | first       |
|     2 | job b   |    3 |      100 | 2019-04-25 12:00:00 | second      |
|     3 | job c   | NULL |     NULL | NULL                | NULL        |
+-------+---------+------+----------+---------------------+-------------+

【讨论】:

    【解决方案3】:
    SELECT
      t1.*,t2.* FROM
      (SELECT
        MAX(id) as id
      FROM
        table2
      WHERE statusid = 100
      GROUP BY jobid) AS f
      JOIN table2 t2
        ON t2.id = f.id
      JOIN table1 t1
        ON t2.jobid = t1.jobid
    

    子查询select查找statusid为100的行的最后一个id,然后根据这个id加入实际的表。

    您可以根据需要使用正确的连接重新排序。

    【讨论】:

    • 那些 LEFT JOIN 并没有做你认为他们正在做的事情。
    猜你喜欢
    • 2020-09-30
    • 1970-01-01
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-13
    • 2015-05-22
    • 1970-01-01
    相关资源
    最近更新 更多