0

我需要一些关于 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

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

4

6 回答 6

1

你没有说明你的数据库产品,但你可以在任何数据库上使用这样的东西:

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

于 2013-05-06T21:47:53.210 回答
1

通常,解决此问题的最佳方法是使用该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;
于 2013-05-06T21:48:15.000 回答
0

假设 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 测试的链接在这里

于 2013-05-06T22:10:42.807 回答
0

假设对于一个申请者 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;
于 2013-05-06T21:53:29.293 回答
0
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'
于 2013-05-06T22:23:03.800 回答
0

尝试这样的事情。

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)
于 2013-05-07T02:23:08.967 回答