iT邦幫忙

0

PHP顯示日期打卡記錄補未上班打卡日期

  • 分享至 

  • xImage

各位大大
不好意思我在寫網頁要顯示打卡記錄
目前遇到一個邏輯上的問題我兜不太起來

假設我搜尋一個區間 2024/1/1~2024/1/10 有3筆打卡資料
我希望沒有搜尋到的日期也要顯示出來但是不顯示資料
我是用PHP寫的 從MSSQL資料裡面撈出來的
想要顯示的樣子如圖
https://ithelp.ithome.com.tw/upload/images/20240329/20148297wiT9IPdLsn.jpg
迴圈我會寫出左邊的但我不太會變成右邊的...
再麻煩大大給個簡單的範例我可以參考修改就可以了...

補充 我是用laravel框架寫的
先搜尋後,在從頁面上利用foreach迴圈撈出來顯示
附上醜醜的程式碼
我有嘗試用for加個日期區間在利用一些if方式判斷但怎麼測試都失敗
不曉得是不是我方向完全錯誤了...
view部分

@foreach ( $Punch_records as $Punch_record )
<tr align="center" valign="middle" height="25px">
    <td>
        {{ $Punch_record->eventDate }}
    </td>
    <td>
        {{ $Punch_record->first_eventTime }}
    </td>
    <td>
        {{ $Punch_record->min_eventTime }}
    </td>
    <td>
        {{ $Punch_record->max_eventTime }}
    </td>
    <td>
        {{ $Punch_record->last_eventTime }}
    </td>
</tr>
@endforeach
@endif

controller部分

$this->Punch_records = DB::connection('sqlsrv_HR')
    ->table('Punch_record')
    ->select('eventDate', 
    DB::raw("MIN(eventTime) AS first_eventTime"),
    DB::raw("MIN(CASE WHEN eventTime BETWEEN '12:00:00' AND '14:00:00' THEN eventTime END) AS min_eventTime"),
    DB::raw("MAX(CASE WHEN eventTime BETWEEN '12:00:00' AND '14:00:00' THEN eventTime END) AS max_eventTime"),
    DB::raw("MAX(eventTime) AS last_eventTime"))
    ->where('personName', $searchEmployee)
    ->whereBetween('eventDate', [$searchDate1, $searchDate2])
    ->groupBy('eventDate')
    ->get();
看更多先前的討論...收起先前的討論...
froce iT邦大師 1 級 ‧ 2024-03-29 11:12:05 檢舉
2種方法:
1. 用SQL直接產生,這邊SQL的高手很多。
2. 用PHP或前端JS先產出日期區間的每個日期,然後每個日期去跟資料庫的資料去做比對。
冰心 iT邦新手 5 級 ‧ 2024-03-29 11:38:43 檢舉
第一點完全我的弱項,目前也正在嘗試搜尋關鍵字看看能不能找到範例
第二點感覺跟我用for的概念好像一樣但不曉得是不是其實是不同的概念,但晚點我也朝這方面查看看
com iT邦新手 4 級 ‧ 2024-03-30 16:11:02 檢舉
本人SQL也是超級弱~有沒有推薦學習SQL指令的好地方?
rogeryao iT邦超人 8 級 ‧ 2024-03-30 18:46:44 檢舉
把 「一級屠豬士」「純真的人」的最佳解答內含 SQL 的案例都看懂 ,
大概可以增加一甲子的功力
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
rogeryao
iT邦超人 8 級 ‧ 2024-03-29 11:57:37
最佳解答
CREATE TABLE XX (
X1 NVARCHAR(50),
X2 NVARCHAR(50));

INSERT INTO XX (X1,X2) VALUES
('2024-01-01','08:55'),
('2024-01-05','08:45'),
('2024-01-09','08:57');
WITH CTE_GetDate AS (
SELECT CONVERT(DATE, '20240101') AS NewDate
UNION ALL
SELECT DATEADD(DAY, 1, NewDate)
FROM CTE_GetDate
WHERE DATEADD(DAY, 1, NewDate) < DATEADD(MONTH, 1,CONVERT(DATE, '20240101'))
)

SELECT NewDate,ISNULL(X2,'') AS NewTime
FROM CTE_GetDate
LEFT JOIN XX ON CONVERT(DATE, XX.X1) = NewDate

Demo

冰心 iT邦新手 5 級 ‧ 2024-03-29 12:04:20 檢舉

太感謝了,這樣我有方向了
我一直卡在死胡同,SQL真的是我的弱項,導致我能避免用SQL就不用SQL
但我其他方面也沒有比較會 QQ

路過,說一下 SQL Server 2022 版有 GENERATE_SERIES()了
文件 按我前往
範例 按我前往

rogeryao iT邦超人 8 級 ‧ 2024-03-29 16:45:30 檢舉

SQL Server 2022 新玩具,玩一下

SELECT NewDate,ISNULL(X2,'') AS NewTime
FROM (  
SELECT CONVERT(DATE, DATEADD(day, value, '2024-01-01')) AS NewDate
FROM GENERATE_SERIES(0, DATEDIFF(day, '2024-01-01', 
  DATEADD(day,-1,DATEADD(MONTH, 1,CONVERT(DATE, '2024-01-01')))))
) AS MONTHTABLE  
LEFT JOIN XX ON CONVERT(DATE, XX.X1) = NewDate

Demo

0
hungho0208
iT邦新手 4 級 ‧ 2024-03-29 11:52:38

就2個table一個是日期 一個是你打卡的table

left join不就能達成你要的嗎?

冰心 iT邦新手 5 級 ‧ 2024-03-29 12:03:29 檢舉

對耶,我一直想要透過view這邊解決卻忘記我可以再建一個表合併...
感謝你,但因為剛好另一位大大有直接提供程式碼了所以我就給另一位大大最佳解答了,還是很感謝您

0
lambo
iT邦見習生 ‧ 2024-04-01 12:03:38

其實也不見得要只利用SQL的方法把資料查出來,可以新增一個array把資料塞進去:

//建立一段連續日期的array,初始化陣列資料
$period = new DatePeriod(new DateTime("2024/1/1"), new DateInterval("P1D"), new DateTime("2024/1/11"));
foreach ($period as $date) {
    $data[$date->format("Y/n/j")] = "";
}
//迭代一次察遜出的資料,塞進剛剛建立的array裡
foreach ($Punch_records as $Punch_record) {
    $data[$Punch_record["eventDate"]] = $Punch_record["eventTime"];
}

我要發表回答

立即登入回答