在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/數據庫/ mysql查詢計算排序的問題

mysql查詢計算排序的問題

簽到表:字段有
用戶id userid
簽到時間 signtime 時間戳類型 int
簽到類型 type 分為 0和1 分別代表 簽到和簽退, 一個用戶一天可以簽兩次, 一次 簽到 一次簽退。 簽到和簽退都是必須在一天,不考慮不在一天。

現在想要把簽到 和簽退 之間的時間(兩個時間相減)查出來 ,并且按照這個時間排序, 最后分組給每個用戶。
這還需要考慮到, 這個用戶有簽到, 沒簽退的情況 。
主要是判斷如果這個用戶都有簽到和簽退就把兩個時間的差值求出來 這個弄出來就好了
這如何寫sql計算呢

回答
編輯回答
安若晴

假設表結構如下

CREATE TABLE `signs` (
  `userid` int(11) NOT NULL,
  `signtime` int(11) NOT NULL,
  `type` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`userid`,`signtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

可以用如下SQL解決

select tmp.*,
    max_signout-min_sign diff  #簽退時間差
    from (
    select 
    date(FROM_UNIXTIME(signtime)) day , 
    userid,
    min(
        case type
        when 0 then
         signtime
        when 1 then
            #這里表示的是一個無窮大的意思,反正就是讓簽退時間不參與比較,
         100000000000
        end
    ) min_sign, #一天中的最早的簽到時間
    max(
        case type
        when 0 then
         0
        when 1 then
         signtime
        end
    ) max_signout #一天中的最晚簽到時間
    from signs 
    group  by 1 ,2
) tmp 
order by diff desc ;

不過沒有考慮到跨天簽到的,比如早上9點打卡,第二天上午7點下班的情況。。。。

2018年7月9日 08:05
編輯回答
悶油瓶

這個需求其實就是用同一個表以 aliased 方式進行聯合查詢而已,但是,由于你的 signtime 是 int 類型,所以,無法按照時間的格式來確定“何為同一天?”,這個條件。

至于你的 signtime 有啥規(guī)律,這得需要你把詳細的內容貼出來。

2017年10月23日 06:19
編輯回答
悶騷型

這表設計的不好。不過按現有這種表結構,你可以考慮簽到表簽到的情況left join簽到表簽退的情況(用left join是考慮有簽到沒有簽退的情況)。比如select .. from 簽到表 A left join 簽到表 B On B.userid=A.userid and B.日期=A.日期 and A.type=0 and B.type=1 ...

推薦其它方案1:如果可以稍微改一下表結構,增加“簽到日期”欄位,用空間換時間,而且對userid和“簽到日期”兩個欄位做一個復合索引,以上的查詢就會很快。而且日常系統(tǒng)中,經常也要判斷用戶同一天是否已經簽到過,有這個復合索引查詢判斷的速度就會很快。

推薦其它方案2:如果表結構可以大改,這種需求可以這樣設計:
簽到表
{
用戶id
userid
簽到日期
簽到時間 signtime 時間戳類型 int
簽退時間
}
也就是增加“簽到日期”欄位,然后把“簽到類型”改成“簽退時間”,這樣的設計簡單又高效。但是它不能記錄同一個用戶同一天兩次簽退的異常情況,這時候可以增加“用戶異常簽到表”或者“日志表”來記錄用戶的異常操作,而“簽到表”只記錄有效的數據。

2017年7月10日 01:34