【问题标题】:Using min() result from subquery returns multiple records使用来自子查询的 min() 结果返回多条记录
【发布时间】:2017-08-17 16:40:51
【问题描述】:

希望这个问题的答案很简单(看起来应该是这样,但我遗漏了一些东西)......我有一个简单的查询,可以从表中获取最小值(通过子查询),然后使用该最小值尝试获得一个简单的months_between最终结果

我试图尽可能简单地回答的问题是:最早的 end_date 是什么时候,这个 end_date 距离 report_date 有多远

这是查询

select end_date term_date, months_between (cast (report_date as date), cast (end_date as date)) term_length
from table1
where end_date = 
  (select min (end_date) end_date
    from table1
    where rec_load_date = (select max (rec_load_date) from table1)
      and active_rec = 'Y' and end_date <= report_date);

我的问题是,虽然子查询完美运行,即我得到一个最小(结束日期)值,但在主查询中使用它会返回多条记录。 (见图片)

当前结果: 1. term_date = min(table1.end_date) 2. term_length = months_between value 比较 table1.report_date 和 table1.end_date(即 table1 中记录的实际 end_date 值)

当前结果(附图):

返回的记录示例(与 table1 中适用的 end_date 值一样多的行)

样本数据:

create table table1 (rec_load_date varchar(25), report_date as varchar (25), end_date as varchar (25));
insert into table1 (rec_load_date, report_date, end_date) values ('2017-08-10', '2017-07-31', '2017-02-28');
insert into table1 (rec_load_date, report_date, end_date) values ('2017-08-10', '2017-07-31', '2017-01-31');
insert into table1 (rec_load_date, report_date, end_date) values ('2017-08-10', '2017-07-31', '2017-04-30');
insert into table1 (rec_load_date, report_date, end_date) values ('2017-08-10', '2017-07-31', '2017-03-31');
insert into table1 (rec_load_date, report_date, end_date) values ('2017-08-10', '2017-07-31', '2017-01-31');
insert into table1 (rec_load_date, report_date, end_date) values ('2017-08-10', '2017-07-31', '2017-04-25');
insert into table1 (rec_load_date, report_date, end_date) values ('2017-08-10', '2017-07-31', '2017-01-31');

关于如何从查询中返回以下结果的任何想法:'2017-01-31', 6

Multiple recs returned

【问题讨论】:

  • 嗯,你有那些记录的 endDate 为 20170131,因此这些行被返回。这里的真正目标是什么?你想用这个查询回答什么问题。
  • 嗨 scsimon,我想要得到的具体答案是:最早的 end_date 是什么,以及这个 end_date 距离 report_date 有多远

标签: sql group-by amazon-redshift


【解决方案1】:

根据您的评论,您可以使用:

select
    report_date
    ,datediff(day,report_date,min(end_date)) as DaysBack
from
    table1
group by 
   report_date

这仍然会为您提供每一行的返回日期。如果您想要最早或最新的report_date,则可以通过TOP 1添加订单

select top 1
    report_date
    ,datediff(day,report_date,min(end_date)) as DaysBack
from
    table1
group by 
    report_date
order by
    report_date asc --or desc

【讨论】:

  • 按原样尝试了您的查询,并且对于您所描述的内容(通过 report_date 获得答案)它确实有效,这么多 THNXS !!!仅供参考...我正在寻找结果中的 min (end_date),而不是 report_date。但我认为你已经给了我足够的东西来弄清楚我需要做出哪些改变才能得到我想要的东西您的解决方案/方法优雅而简单,我倾向于使我的解决方案比他们需要的更复杂
  • 嘿scsimon:我稍微调整了您的查询并得到了我需要的结果。同样,您的方法非常简单和优雅,我需要开始这样思考:)。谢了!!!!!!
  • @Gar 很容易让事情变得过于复杂。我们都这样做并逐渐变得更好。
【解决方案2】:

看起来您的示例数据不完整,但我暂时忽略缺少的rec_load_date,并假设您的SELECT MIN(end_date) 将正确返回一个值:2017-01-31

但随后外部查询有效地搜索 select all rows from table1 where end_date = '2017-01-31' 并且有 3 行(在您的示例数据中,可能在您的真实表中更多)符合此条件。所以您得到了多行!

如果您只想获得一行,您将不得不更加专门地确定它。使用ROW_NUMBER() OVER(...ORDER BY x) 对行进行编号,然后选择rownumber 为1 的行是一种方法,即使存在重复也是如此。不过要注意;如果您对存在多个相同值的 end_date 之类的东西进行天真排序,那么您没有简单的方法来保证 WHICH 行的编号为 1。要么增加您排序的列数,要么选择不同的排序键。

【讨论】:

  • 感谢您的回复并提供一些见解。主要是我对主查询将要执行的操作的“从 table1 中选择所有行,其中 end_date = '2017-01-31'”性质表示不满。我仍然没有真正的答案。也许我应该重新考虑整个方法......?我要问的问题是:最早的 end_date 是什么,以及这个 end_date 距离 report_date 有多远。注意:所有记录值都具有相同的 report_date '2017-07-31'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-25
  • 2023-04-09
  • 1970-01-01
  • 2012-08-25
  • 2011-01-31
  • 1970-01-01
相关资源
最近更新 更多