Skip to content

Commit 5280161

Browse files
authored
website (#1635)
docs: website article about pq
1 parent c69af1f commit 5280161

2 files changed

Lines changed: 105 additions & 1 deletion

File tree

website/content/posts/2023-01-07-functional-relations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: A functional approach to relational queries
33
date: 2023-01-07
4-
authors: ["aljazerzen"]
4+
authors: ["Aljaž Mur Eržen"]
55
layout: article
66
toc: true
77
url: functional-relations
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
---
2+
title: Time tracking with pq
3+
date: 2023-01-27
4+
authors: ["Aljaž Mur Eržen"]
5+
layout: article
6+
---
7+
8+
Some time ago, I needed a time-tracking app that would be simple and fast. After
9+
looking into a few heavy web applications, I settled with this one-liner:
10+
11+
```
12+
# time_tracker.sh
13+
echo $(date -u +"%Y-%m-%dT%H:%M:%SZ"),$1 >> ~/time-tracking.csv
14+
```
15+
16+
I've made it a bit more sophisticated, but the core functionality is the same.
17+
The the script is aliased to `tt`, so I can start or stop the timer in any open
18+
terminal by writing:
19+
20+
```
21+
$ tt start
22+
$ tt stop
23+
```
24+
25+
I've prefilled the resulting `~/time-tracking.csv` with a header, so it is ready
26+
to be analyzed.
27+
28+
```
29+
time,action
30+
2023-01-27T09:26:33Z,start
31+
2023-01-27T10:12:50Z,stop
32+
2023-01-27T12:54:04Z,start
33+
2023-01-27T15:12:07Z,stop
34+
```
35+
36+
Now, I'd want to transform this data to show the total duration for each day.
37+
38+
For this I can use [prql-query](https://github.com/PRQL/prql-query), which is a
39+
CLI which can execute PRQL queries against database engines. At the time of
40+
writing it supports duckdb and datafusion, but we can also connect to many other
41+
engines through these two.
42+
43+
But I don't need that today, plain duckdb will do:
44+
45+
```
46+
$ pq --backend=duckdb \
47+
--from "tt=~/time-tracking.csv" \
48+
'{here comes the PRQL query below}'
49+
```
50+
51+
```prql
52+
# function declaration that is a wrapper for substr SQL function
53+
func substr text start len -> s"substr({text}, {start}, {len})"
54+
55+
56+
# start of the pipeline
57+
from tt # as declared in --from
58+
59+
# compute a few new columns
60+
derive [
61+
date = substr time 0 11, # call the substr function to
62+
# extract date from column `time`
63+
prev_action = lag 1 action, # lag column `action`
64+
prev_time = lag 1 time, # lag column `time`
65+
]
66+
67+
# pick only rows that correspond to intervals that I want to track
68+
filter action == "stop" and prev_action == "start"
69+
70+
# for each date
71+
group date (
72+
# sum durations of those intervals
73+
aggregate [sec = sum s"EXTRACT(EPOCH FROM {time - prev_time})"]
74+
)
75+
76+
# compute more columns
77+
derive [
78+
hours = substr f"00{sec / (60 * 60)}" 0-2 2,
79+
minutes = substr f"00{(sec / 60) % 60}" 0-2 2,
80+
seconds = substr f"00{sec % 60}" 0-2 2,
81+
]
82+
83+
# expose only date and pretty-printed duration
84+
select [
85+
date,
86+
duration = f"{hours}:{minutes}:{seconds}"
87+
]
88+
```
89+
90+
When run on the file above, prql-query produces this pretty table:
91+
92+
```
93+
+------------+----------+
94+
| date | duration |
95+
+------------+----------+
96+
| 2023-01-27 | 03:04:20 |
97+
+------------+----------+
98+
```
99+
100+
The full code of my script can be
101+
[found here](https://github.com/aljazerzen/dotfiles/blob/aebe07e90b5dc86b3974946ded921bdee22e95e8/scripts/tt).
102+
103+
If you want to see how looked when implemented with SQL and SQLite3, see this
104+
[old revision of the file](https://github.com/aljazerzen/dotfiles/blob/fe732ec72e4f4066bfe19041e7d71685dbf69184/scripts/tt).

0 commit comments

Comments
 (0)