2013-05-06 57 views
0

我需要一點幫助,使用sql查詢。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 

我怎麼能去關於完成這樣的事情,最好只使用連接和沒有嵌套的選擇?

+3

您正在使用哪個數據庫服務器/版本? – imthepitts 2013-05-06 21:40:32

+0

歡迎使用堆棧溢出。供應商的功能差異很大。因此,將*數據庫類型和版本包含* all *查詢問題是一個好主意。 – Leigh 2013-05-06 22:31:15

+0

我正在運行5.5 MySQL服務器 – petrasadi 2013-05-07 16:49:03

回答

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; 
+0

未測試第一個解決方案,但第二個解決方案非常好。謝謝你的幫助。 – petrasadi 2013-05-07 19:11:35

+0

@petrasadi。 。 。第一個在MySQL中不起作用。第二個是與MySQL相關的。 – 2013-05-07 19:22:03

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 with Demo

+0

感謝您的回覆。如果加入條件的「t1.id = t2.id」行被刪除,則您的解決方案可以很好地工作。 – petrasadi 2013-05-07 19:10:41

0

假設爲一個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; 
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測試是here

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' 
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)