-
Notifications
You must be signed in to change notification settings - Fork 0
Home
david8 – the next generation Weyland Robot is lightweight Python SQL builder. I initially started this project just for fun, and I really hope it's turning out to be quite decent and visually pleasing.
I rewrote the interface many times and I might have forgotten or overlooked something in the design so feel free to open a bug report / feature request / question
To be honest, the project was originally started simply to avoid template engines and patterns like if something: f"AND {conditions}" else: "", f"{query} UNION …" inside scripts or pipelines. It was also meant to provide a clean way to do things like:
# somewhere in your data debug script / notebook
from datetime import datetime, timedelta
from david8 import get_default_qb
from david8.expressions import val
from david8.functions import count
from david8.predicates import lt, gt, eq, between
qb = get_default_qb()
class UQueries:
@staticmethod
def last_active():
end = datetime.now()
start = end - timedelta(days=10)
return (
qb
.select('*')
.from_table('users')
.where(
between('last_login_day', val(str(start.date())), val(str(end.date()))),
eq('status', val('active')),
)
)
query = (qb
.with_(
('group_a', UQueries.last_active().where(lt('age', 18), gt('height', 150))),
('group_b', UQueries.last_active().where(gt('age', 30), gt('height', 170))),
)
.select(
count('*').as_('total_users'),
'age',
'gender',
'last_login_day',
)
.from_query(
qb
.select('age', 'gender', 'last_login_day')
.from_table('group_a')
.union(qb.select('age', 'gender', 'last_login_day').from_table('group_b'))
)
.group_by('age', 'gender', 'last_login_day')
.order_by_desc('total_users', 'last_login_day')
.limit(10)
)
print(query.get_sql())
# WITH group_a AS (
# SELECT * FROM users
# WHERE last_login_day BETWEEN '2025-12-07' AND '2025-12-10'
# AND status = 'active'
# AND age < %(p1)s
# AND height > %(p2)s
# ),
# group_b AS (
# SELECT * FROM users
# WHERE last_login_day BETWEEN '2025-12-07' AND '2025-12-10'
# AND status = 'active'
# AND age > %(p3)s
# AND height > %(p4)s
# )
# SELECT count(*) AS total_users,
# age,
# gender,
# last_login_day
# FROM (
# SELECT age,
# gender,
# last_login_day
# FROM group_a
# UNION ALL
# SELECT age, gender, last_login_day
# FROM group_b
# )
# GROUP BY age,
# gender,
# last_login_day
# ORDER BY total_users DESC,
# last_login_day DESC
# LIMIT 10
print(query.get_parameters())
# {'p1': 18, 'p2': 150, 'p3': 30, 'p4': 170}IDE-friendly
SQL query from benchmarks. Syntax comparison: pypika, sqlalchemy, david8.
0.1.0b1 results:
-
beta, waiting for bug reports / features
See QuickStart, tests and milestones

