RosettaCodeData/Task/Merge-and-aggregate-datasets/FreeBASIC/merge-and-aggregate-datasets-2.basic
2025-06-11 20:16:52 -04:00

248 lines
6.9 KiB
Text

#include once "sqlite3.bi"
#include once "string.bi"
#include once "crt.bi"
' Callback para SQLite
Function callback Cdecl (Byval NotUsed As Any Ptr, Byval argc As Integer, _
Byval argv As ZString Ptr Ptr, Byval colName As ZString Ptr Ptr) As Integer
For i As Integer = 0 To argc - 1
If argv[i] <> NULL Then
Print *colName[i] & ": " & *argv[i] & " ";
Else
Print *colName[i] & ": NULL ";
End If
Next
Print
Return 0
End Function
Sub createCSVfiles()
Dim As Integer ff
If Dir("patients.csv") = "" Then
ff = Freefile
Open "patients.csv" For Output As #ff
Print #ff, "PATIENT_ID,LASTNAME"
Print #ff, "1001,Hopper"
Print #ff, "4004,Wirth"
Print #ff, "3003,Kemeny"
Print #ff, "2002,Gosling"
Print #ff, "5005,Kurtz"
Close #ff
End If
If Dir("visits.csv") = "" Then
ff = Freefile
Open "visits.csv" For Output As #ff
Print #ff, "PATIENT_ID,VISIT_DATE,SCORE"
Print #ff, "2002,2020-09-10,6.8"
Print #ff, "1001,2020-09-17,5.5"
Print #ff, "4004,2020-09-24,8.4"
Print #ff, "2002,2020-10-08,"
Print #ff, "1001,,6.6"
Print #ff, "3003,2020-11-12,"
Print #ff, "4004,2020-11-05,7.0"
Print #ff, "1001,2020-11-19,5.3"
Close #ff
End If
End Sub
Sub createTableHeaders(db As sqlite3 Ptr)
Dim As ZString Ptr errMsg = NULL
' Create the patient and visit table
sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS patients (PATIENT_ID INT, LASTNAME TEXT);", Cast(Any Ptr, @callback), NULL, @errMsg)
If errMsg <> NULL Then
Print "Error creating patients table: " & *errMsg
sqlite3_free(errMsg)
End If
sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS visits (PATIENT_ID INT, VISIT_DATE TEXT, SCORE NUMERIC(4,1));", Cast(Any Ptr, @callback), NULL, @errMsg)
If errMsg <> NULL Then
Print "Error creating visits table: " & *errMsg
sqlite3_free(errMsg)
End If
End Sub
Sub fillTablesFromCSV(db As sqlite3 Ptr)
Dim As Integer ff, i
Dim As String lineaCSV, query
Dim As ZString Ptr errMsg = NULL
ff = Freefile
Open "patients.csv" For Input As #ff
Line Input #ff, lineaCSV ' Saltar la cabecera
While Not Eof(ff)
Line Input #ff, lineaCSV
Dim As String id = "", lastname = ""
i = 1
While i <= Len(lineaCSV) And Mid(lineaCSV, i, 1) <> ","
id += Mid(lineaCSV, i, 1)
i += 1
Wend
i += 1 ' Skip the comma
While i <= Len(lineaCSV)
lastname += Mid(lineaCSV, i, 1)
i += 1
Wend
query = "INSERT INTO patients VALUES (" & id & ", '" & lastname & "');"
sqlite3_exec(db, query, NULL, NULL, @errMsg)
If errMsg <> NULL Then
Print "Error inserting patient: " & *errMsg
sqlite3_free(errMsg)
End If
Wend
Close #ff
ff = Freefile
Open "visits.csv" For Input As #ff
Line Input #ff, lineaCSV ' Skip header
While Not Eof(ff)
Line Input #ff, lineaCSV
Dim As String id = "", dateStr = "", score = ""
Dim As Integer fieldNum = 0
For i = 1 To Len(lineaCSV)
If Mid(lineaCSV, i, 1) = "," Then
fieldNum += 1
Else
Select Case fieldNum
Case 0: id += Mid(lineaCSV, i, 1)
Case 1: dateStr += Mid(lineaCSV, i, 1)
Case 2: score += Mid(lineaCSV, i, 1)
End Select
End If
Next i
query = "INSERT INTO visits VALUES (" & id & ", "
If dateStr = "" Then
query &= "NULL, "
Else
query &= "'" & dateStr & "', "
End If
If score = "" Then
query &= "NULL);"
Else
query &= score & ");"
End If
sqlite3_exec(db, query, NULL, NULL, @errMsg)
If errMsg <> NULL Then
Print "Error inserting visit: " & *errMsg
sqlite3_free(errMsg)
End If
Wend
Close #ff
End Sub
Function joinTablesAndGroup(db As sqlite3 Ptr) As String
Dim As sqlite3_stmt Ptr stmt
Dim As String result = ""
Dim As ZString Ptr errMsg = NULL
Dim As String query = _
"SELECT " & _
" p.PATIENT_ID, " & _
" p.LASTNAME, " & _
" MAX(v.VISIT_DATE) AS LAST_VISIT, " & _
" SUM(v.SCORE) AS SCORE_SUM, " & _
" ROUND(AVG(v.SCORE), 1) AS SCORE_AVG " & _
"FROM " & _
" patients p " & _
"LEFT JOIN " & _
" visits v ON p.PATIENT_ID = v.PATIENT_ID " & _
"GROUP BY " & _
" p.PATIENT_ID, p.LASTNAME " & _
"ORDER BY " & _
" p.PATIENT_ID;"
If sqlite3_prepare_v2(db, query, -1, @stmt, NULL) <> SQLITE_OK Then
Print "Error preparing statement: " & *sqlite3_errmsg(db)
Return "Error"
End If
result = "| PATIENT_ID | LASTNAME | LAST_VISIT | SCORE_SUM | SCORE_AVG |" & Chr(10)
result &= "|------------|----------|------------|-----------|-----------|" & Chr(10)
While sqlite3_step(stmt) = SQLITE_ROW
Dim As String row = "| "
' PATIENT_ID
If sqlite3_column_type(stmt, 0) <> SQLITE_NULL Then
row &= " " & Trim(Str(sqlite3_column_int(stmt, 0))) & " | "
Else
row &= Space(10) & "| "
End If
' LASTNAME
If sqlite3_column_type(stmt, 1) <> SQLITE_NULL Then
Dim As String lastname = *Cast(ZString Ptr, sqlite3_column_text(stmt, 1))
row &= lastname & Space(9 - Len(lastname)) & "| "
Else
row &= " | "
End If
' LAST_VISIT
If sqlite3_column_type(stmt, 2) <> SQLITE_NULL Then
Dim As String visit_date = *Cast(ZString Ptr, sqlite3_column_text(stmt, 2))
row &= visit_date & Space(11 - Len(visit_date)) & "| "
Else
row &= " None | "
End If
' SCORE_SUM
If sqlite3_column_type(stmt, 3) <> SQLITE_NULL Then
Dim As Double score_sum = sqlite3_column_double(stmt, 3)
row &= " " & Format(score_sum, "#00.#") & " | "
Else
row &= " None | "
End If
' SCORE_AVG
If sqlite3_column_type(stmt, 4) <> SQLITE_NULL Then
Dim As Double score_avg = sqlite3_column_double(stmt, 4)
row &= " " & Format(score_avg, "##.#") & " |"
Else
row &= " None |"
End If
result &= row & Chr(10)
Wend
sqlite3_finalize(stmt)
Return result
End Function
' Main program
Dim As sqlite3 Ptr db
Dim As Integer rc
createCSVfiles()
rc = sqlite3_open(":memory:", @db)
If rc <> SQLITE_OK Then
Print "Error opening database: " & *sqlite3_errmsg(db)
sqlite3_close(db)
Sleep: End 1
End If
createTableHeaders(db)
fillTablesFromCSV(db)
Dim As String result = joinTablesAndGroup(db)
Print result
sqlite3_close(db)
Sleep