繁体   English   中英

SQL查询 - 从同一行中的一个表打印最小值和最大值

[英]SQL query - print the min and max from one table in the same row

我需要一些sql查询的帮助。

我有一个表格,其格式和数据如下所示:

id | applicant_id | application_status | status_time
1  | 1234         | received           | 2013-05-06 15:00:00
1  | 1234         | pending            | 2013-05-06 15:30:00
1  | 1234         | approved           | 2013-05-06 16:00:00

我需要解决的问题必须打印以下内容:

applicant_id | initial_status | initial_time        | current_status | current_status_time
1234         | received       | 2013-05-06 15:00:00 | approved       | 2013-05-06 16:00:00

我怎么能完成这样的事情,最好只使用连接而不是嵌套选择?

您没有说明您的数据库产品,但您可以在任何数据库上使用类似的东西:

select t1.id,
  t1.applicant_id,
  max(case when t1.status_time = t2.mintime then t1.application_status end) initial_status,
  max(case when t1.status_time = t2.mintime then t1.status_time end)initial_time,
  max(case when t1.status_time = t2.maxTime then t1.application_status end) current_status,
  max(case when t1.status_time = t2.maxTime then t1.status_time end) `current_time`
from yourtable t1
inner join
(
  select id, applicant_id,
    max(status_time) maxTime,
    min(status_time) mintime
  from yourtable
  group by id, applicant_id
) t2
  on t1.id = t2.id
  and t1.applicant_id = t2.applicant_id
  and 
  (
    t1.status_time = t2.mintime
    or t1.status_time = t2.maxtime
  )
group by t1.id, t1.applicant_id;

请参阅SQL Fiddle with Demo

一般来说,解决此问题的最佳方法是使用row_number()函数。 但是,这需要嵌套选择:

select t.applicant_id,
       max(case when seqnum_asc = 1 then status end) as initial_status,
       max(case when seqnum_asc = 1 then status_time end) as initial_time,
       max(case when seqnum_desc = 1 then status end) as current_status,
       max(case when seqnum_desc = 1 then status_time end) as current_time
from (select t.*,
             row_number() over (partition by applicant_id order by status_time) as seqnum_asc,
             row_number() over (partition by applicant_id order by status_time desc) as seqnum_desc
      from t
     ) t
group by t.applicant_id;

如果您的数据库不支持row_number() ,为了便于阅读,我建议使用相关子查询。 但那些也是嵌套的。 这是一个满足您要求的MySQL解决方案:

select t.applicant_id,
       substring_index(group_concat(status) separator ',' order by status_time), ',', 1) as initial_status,
       min(status_time) as initial_time,
       substring_index(group_concat(status) separator ',' order by status_time desc), ',', 1) as current_status,
       max(status_time) as current_time
from t
group by t.applicant_id;

假设对于一个applicant_id,您有一行“已收到”状态,另一行有“已批准”状态(如您在问题中列出的那样),您可以使用内联视图来解决您的问题:

select section1.applicant_id AS applicant_id, 'received' AS initial_status, 
       section1.status_time AS initial_time, 'approved' AS current_status,
       section2.status_time AS current_status_time from    
   (select applicant_id, status_time from yourtable where application_status = 'received') section1,   
   (select applicant_id, status_time from yourtable where application_status = 'approved') section2 
   where section1.applicant_id = section2.applicant_id;

假设MS SQL(Transact-SQL),并且您的源表被恰当地命名为[SourceTable]。 =)

SELECT DISTINCT
                [Probe].applicant_id,
                [LogMin].application_status     [initial_status], 
                [LogMin].status_time            [initial_time],
                [LogMax].application_status     [current_status], 
                [LogMax].status_time            [current_status_time]
FROM            (
                SELECT      MAX(status_time)    [MaxDate],
                            MIN(status_time)    [MinDate],
                            [applicant_id]
                FROM        [SourceTable]
                GROUP BY    [applicant_id]
                )           [Probe]
INNER JOIN      [SourceTable]                   [LogMax]
        ON      [Probe].[applicant_id]      =   [LogMax].[applicant_id]
        AND     [Probe].[MaxDate]           =   [LogMax].[status_time]
INNER JOIN      [SourceTable]                   [LogMin]
        ON      [Probe].[applicant_id]      =   [LogMin].[applicant_id]
        AND     [Probe].[MinDate]           =   [LogMin].[status_time]

链接到SQLFiddle测试就在这里

SELECT  a.application_id
        , a.application_status as initial_status
        , a.status_time as initial_time
        , b.application_status as current_status
        , b.status_time as current_status_time  
FROM        sample1 A
CROSS JOIN sample1  B
WHERE   A.application_status = 'received'
and b.  application_status = 'approved'

尝试这样的事情。

select
    t1.applicant_id,
    t2.application_status initial_status,
    t1.initial_time,
    t3.application_status current_status,
    t1.current_status_time
from
    (select
          applicant_id,
          min(status_time) initial_time,
          max(status_time) current_status_time
    from
        your_table
    group by
         applicant_id) t1
    inner join your_table t2
        on (t1.applicant_id = t2.applicant_id and t1.initial_time = t2.status_time)
    inner join your_table t3
        on (t1.applicant_id = t3.applicant_id and t1.current_status_time = t3.status_time)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM