【问题标题】:how to simplify this sql如何简化这个sql
【发布时间】:2020-12-31 18:45:46
【问题描述】:

我的 sql 表达式有问题,我想在主选择中放置不同的列,这些不同的列具有相同的 where 子句。

这是我的 sql 示例:

SELECT t.*,

  (SELECT monitor_value
   FROM sub_message s
   WHERE s.project_name=t.project_name
   ORDER BY monitor_time ASC
   LIMIT 1) AS project_start_val,

  (SELECT monitor_time
   FROM sub_message s
   WHERE s.project_name=t.project_name
   ORDER BY monitor_time ASC
   LIMIT 1) AS project_start_time
FROM sub_message t

【问题讨论】:

标签: mysql where-clause mysql5


【解决方案1】:

您的查询显示所有子消息及其最旧的监控时间和值。直接的方法是使用窗口函数(即带有OVER 子句的聚合函数)。这些从 MySQL 8 开始可用。

FIRST_VALUE最简单的方法:

select 
  sm.*,
  first_value(monitor_value) over oldest_first as project_start_val,
  first_value(monitor_time) over oldest_first as project_start_time
from sub_message sm
window oldest_first as (partition by project_name order by monitor_time);

您还可以在 from 子句中获取每个项目的第一行:

select 
  sm.*,
  smm.monitor_value as project_start_val,
  smm.monitor_time as project_start_time
from sub_message sm
join
(
  select sm2.*, min(monitor_time) over (partition by project_name) as min_monitor_time
  from sub_message sm2
) smm on smm.project_name = sm.project_name and smm.monitor_time = smm.min_monitor_time;

在 MySQL 8 之前,窗口函数不可用。在那里,您必须再次从表中进行选择。例如:

select 
  sm.*,
  smm.monitor_value as project_start_val,
  smm.monitor_time as project_start_time
from sub_message sm
join sub_message smm
  on smm.project_name = sm.project_name
  and (smm.project_name, smm.monitor_time) in
  (
    select project_name, min(monitor_time)
    from sub_message
    group by project_name
  );

【讨论】:

    【解决方案2】:

    以下应该可以工作(未经测试):

    select t.*,
      s2.monitor_value project_start_val,  
      s2.monitor_time project_start_time
    from sub_message t
    LEFT JOIN (select project_name pn, min(monitor_time) pt from sub_message group by project_name) s1 ON pn=t.project_name
    LEFT JOIN sub_message s2 ON s2.project_name=s1.pn and s2.monitor_time=s1.pt
    

    您仍然需要LEFT JOIN 两次,并且只有当project_name,monitor_time 列在表sub_message 中是唯一的时它才能可靠地工作。但是,如果满足此条件,则您可以在查询中包含更多 s2 列,而无需添加另一个子查询。

    【讨论】:

    • 如果monitor_time 不是唯一的(我怀疑此列是否被定义为唯一),那么您的查询将给出很多行,而不是 OP 的查询收到的一行。
    • 这正是我在帖子中所说的:project_namemonitor_time 的组合必须是唯一的。由于我不知道实际数据,我无法确定更多信息,但如果数字 primary key 可用于表 sub_message,那将很有帮助。然后我们可以将第二个LEFT JOIN 基于该唯一键。
    猜你喜欢
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 2021-12-04
    • 1970-01-01
    • 2019-10-10
    • 2015-02-04
    相关资源
    最近更新 更多