Selecting and indexing¶
Each selection is a child: it refers to rows of its parent, and runs no query until it is read.
Indexing with brackets¶
__getitem__ ¶
__getitem__(sel)
Select rows by position or by key, as daf[n], daf[n:m] and daf[key] do.
Each gives a selection, not an ordinary Daf, so a large slice stays in the database.
Read it with to_daf(), or to_dict() for one row. For one row as a dict, iloc() and
select_record() are cheaper: they make no selection.
- An int is always a position, from 0, even when the keyfield holds ints. Negative counts
from the end. A position past the end raises IndexError, as in a Daf. For an int key,
use
select_record(), orselect_records_daf()for several. - A slice of positions, as in
sdaf[10:20]. A step is not supported yet. A slice past the end is empty, as in a Daf. - A str is a key. The keyfield's unique index is made first. A missing key raises KeyError, as in a Daf.
- A list of keys gives their rows in the order of the list, as
select_records_daf()does. A missing key raises KeyError, as in a Daf.
Rows and columns together, as in sdaf[key, 'col'] or sdaf[:, ['a', 'b']], give new
rows with only those columns, as select_cols() makes them. The rows part takes any form
above, or : for all rows. The columns part is a name, a list of names, or : for all.
Read one value with to_value(), as in a Daf.
A value read this way makes a TEMP table, which costs about 1 ms. In a loop over many
keys, select_record() is about 30 times faster.
A negative position, or a slice with a negative end, costs a len() first. In a parent
with daf_rid, or a child whose rows are found, positions are looked up directly. Otherwise
SQLite steps over the rows before them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sel
|
Any
|
An int, a slice, a key or a list of keys. Or a pair of rows and columns. |
required |
Returns:
| Type | Description |
|---|---|
SqlDaf
|
A selection. New rows of the chosen columns, for a pair. |
Raises:
| Type | Description |
|---|---|
IndexError
|
An int position past the end. |
KeyError
|
A key that is missing, or a name that is not a column. |
NotImplementedError
|
Any other form, such as a list of positions, or a slice with a step. |
ValueError
|
An int or a slice, on a parent that has had rows deleted. See SqlDaf. |
Examples:
>>> import tempfile
>>> SqlDaf.db_path = tempfile.mkdtemp() + '/job.db'
>>> marks_sdaf = SqlDaf('marks', cols=['ballot_id', 'v'], lol=[['b1', 1], ['b2', 0], ['b3', 1]], keyfield='ballot_id')
>>> marks_sdaf[['b3', 'b1']].to_daf().to_lod()
[{'ballot_id': 'b3', 'v': 1}, {'ballot_id': 'b1', 'v': 1}]
>>> marks_sdaf['b2', 'v'].to_value()
0
By condition¶
select_where ¶
select_where(where, indirect_col=None, cols=None)
Select the rows for which a Python function is true, as Daf.select_where() does.
The function gets each row as a KeyedList, with Python NULL for
a missing value, and reads cells by name, as in row['n']. It is registered with SQLite
and called for each row when the selection is first read. If it raises, that error is
raised, as itself.
Name the columns it reads in cols. It is then given only those, which is faster. A row
of every column costs about 1 us. If the test only compares columns to values, use
select_by_dict() or select_where_sql(), which call no Python function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
where
|
Callable[[Any], Any]
|
A function of a row, true for the rows to keep. |
required |
indirect_col
|
str | None
|
Not supported on a SqlDaf yet. |
None
|
cols
|
T_ls | None
|
The columns the function reads. All if None. |
None
|
Returns:
| Type | Description |
|---|---|
SqlDaf
|
A selection. |
Raises:
| Type | Description |
|---|---|
KeyError
|
A name in |
NotImplementedError
|
|
Examples:
>>> import tempfile
>>> SqlDaf.db_path = tempfile.mkdtemp() + '/job.db'
>>> marks_sdaf = SqlDaf.from_daf(Daf(lol=[['b1', 1], ['b2', 0]], cols=['ballot_id', 'v']), name='marks')
>>> marks_sdaf.select_where(lambda row: row['v'] == 1, cols=['v']).to_list()
['b1', 1]
select_where_sql ¶
select_where_sql(where_sql, params=())
Select the rows for which a SQL condition is true.
The condition is the text after WHERE. Name the columns as they are, in double quotes if
they need it, and pass values as params, with ? in the text. Python NULL in params
becomes SQL NULL. Test for a missing value with IS NULL. This is the fastest way to select,
since SQLite does all the work.
Nothing runs yet. The rows are found when the selection is first read. See SqlDaf.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
where_sql
|
str
|
The condition, as SQL text. |
required |
params
|
Iterable[Any]
|
Values for the |
()
|
Returns:
| Type | Description |
|---|---|
SqlDaf
|
A selection. |
Examples:
>>> import tempfile
>>> SqlDaf.db_path = tempfile.mkdtemp() + '/job.db'
>>> marks_sdaf = SqlDaf.from_daf(Daf(lol=[['b1', 1], ['b2', 0]], cols=['ballot_id', 'v']), name='marks')
>>> marks_sdaf.select_where_sql('"v" = ?', [0]).to_list()
['b2', 0]
select_by_dict ¶
select_by_dict(
selector_da, expectmax=-1, inverse=False, keyfield=""
)
Select the rows that match every field of a dict, or any one of a list of dicts.
It works as Daf.select_by_dict() does, with the SQL written for you. A dict is an AND of
equalities, and a list of dicts is an OR of those. With inverse=True, the rows that do
not match. An empty dict matches every row, and an empty list none. A dict that names a
column that is not there matches no row. Python NULL as a value matches a missing value.
Values are compared with SQL's IS, which treats SQL NULL as a value, so the inverse keeps rows with a missing value. As in Python, 1 equals 1.0, and the text '1' does not equal 1.
Nothing runs yet, unless expectmax is given: then its rows are found at once, to
count the matches.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
selector_da
|
T_da | List[T_da]
|
A dict of column and value, or a list of such dicts. |
required |
expectmax
|
int
|
If not -1, and more rows match, raise LookupError. |
-1
|
inverse
|
bool
|
If True, select the rows that do not match. |
False
|
keyfield
|
str
|
The keyfield of the selection. This SqlDaf's if empty. |
''
|
Returns:
| Type | Description |
|---|---|
SqlDaf
|
A selection. |
Raises:
| Type | Description |
|---|---|
LookupError
|
More than |
TypeError
|
|
Examples:
>>> import tempfile
>>> SqlDaf.db_path = tempfile.mkdtemp() + '/job.db'
>>> marks_sdaf = SqlDaf.from_daf(Daf(lol=[['b1', 1], ['b2', '']], cols=['ballot_id', 'v']), name='marks')
>>> marks_sdaf.select_by_dict({'v': ''}).to_list()
['b2', '']
split_where ¶
split_where(where, *, indirect_col=None, cols=None)
Split the rows in two, by a Python function that is true or false for each row.
This is deprecated, as Daf.split_where() is. Use group_where() with a function that
returns True or False.
It works as Daf.split_where() does, with the rows staying in the database. It is two
calls of select_where(): one keeps the rows where the function is true, and the other
the rest. Nothing runs yet. Each side is found when it is first read, and the function is
called again for each side that is read. So it should give the same answer each time.
Name the columns the function reads in cols, as in select_where(). If the test is
that columns equal values, two calls of select_by_dict(), the second with inverse=True,
are much faster, since they call no function. On 1,000,000 rows, reading both sides took
1.79 s here, and 0.21 s that way.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
where
|
Callable[[Any], Any]
|
A function of a row, true for the rows of the first side. |
required |
indirect_col
|
str | None
|
Not supported on a SqlDaf yet. |
None
|
cols
|
T_ls | None
|
The columns the function reads. All if None. |
None
|
Returns:
| Type | Description |
|---|---|
Tuple[SqlDaf, SqlDaf]
|
A tuple of the selection of the rows where the function is true and the selection of the others. |
Raises:
| Type | Description |
|---|---|
KeyError
|
A name in |
NotImplementedError
|
|
Examples:
>>> import tempfile
>>> SqlDaf.db_path = tempfile.mkdtemp() + '/job.db'
>>> marks_sdaf = SqlDaf.from_daf(Daf(lol=[['b1', 10], ['b2', 20], ['b3', 30]], cols=['ballot_id', 'n']), name='marks')
>>> big_sdaf, small_sdaf = marks_sdaf.split_where(lambda row: row['n'] > 10, cols=['n'])
>>> big_sdaf.to_daf().lol, small_sdaf.to_daf().lol
([['b2', 20], ['b3', 30]], [['b1', 10]])
select_first_row_by_dict ¶
select_first_row_by_dict(selector_da, inverse=False)
Get the first row that matches every field of a dict, as Daf.select_first_row_by_dict() does.
The matching rule is that of select_by_dict(). The search stops at the first match.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
selector_da
|
T_da
|
The column names and the values they must have. |
required |
inverse
|
bool
|
If True, find the first row that does not match. |
False
|
Returns:
| Type | Description |
|---|---|
T_da
|
The row as a dict, or an empty dict if none matches. |
Columns¶
select_cols ¶
select_cols(cols=None, exclude_cols=None)
Make a new table with only some columns, chosen by name, as Daf.select_cols() does.
The columns come in the order of cols. A name given twice is used once. A name that is
not a column raises KeyError. With no cols, all columns are kept, in this table's order.
Then exclude_cols leaves out the columns you name. A name in exclude_cols that is not
a column is ignored. The rows keep their order.
The result is new rows, as in a Daf, not a selection of this table's rows. It is resolved the first time it is read, into a TEMP table, as a join is. The keyfield and dtypes carry over for the columns kept.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cols
|
T_ls | None
|
The names of the columns to keep, in the order you want. If empty, all columns. |
None
|
exclude_cols
|
T_ls | None
|
The names of the columns to leave out. |
None
|
Returns:
| Type | Description |
|---|---|
SqlDaf
|
A SqlDaf of the chosen columns, resolved when first read. |
Raises:
| Type | Description |
|---|---|
KeyError
|
A name in |
Examples:
>>> import tempfile
>>> SqlDaf.db_path = tempfile.mkdtemp() + '/job.db'
>>> marks_sdaf = SqlDaf('marks', cols=['ballot_id', 'v', 'n'], lol=[['b1', 1, 10], ['b2', 0, 20]], keyfield='ballot_id')
>>> marks_sdaf.select_cols(['n', 'ballot_id']).to_daf().lol
[[10, 'b1'], [20, 'b2']]
>>> marks_sdaf.select_cols(exclude_cols=['v']).columns()
['ballot_id', 'n']
calc_cols ¶
calc_cols(
include_cols=None,
exclude_cols=None,
include_types=None,
exclude_types=None,
)
Choose column names by rules, as Daf.calc_cols() does.
It reads only the column names and the dtypes, never the rows.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
include_cols
|
Iterable | None
|
Keep only these names. |
None
|
exclude_cols
|
Iterable | None
|
Leave out these names. |
None
|
include_types
|
List[Type] | None
|
Keep only columns whose dtype is one of these. |
None
|
exclude_types
|
List[Type] | None
|
Leave out columns whose dtype is one of these. |
None
|
Returns:
| Type | Description |
|---|---|
T_ls
|
The chosen column names, in column order. |
By key¶
__contains__ ¶
__contains__(key)
Say whether a row has this key, as in key in sdaf.
It is one lookup on the keyfield, through its index. A table with no rows contains nothing, as in a Daf.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Any
|
The key to look for. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if a row has this key. |
Raises:
| Type | Description |
|---|---|
ValueError
|
There is no keyfield, and there are rows. |
keys ¶
keys()
Get the keys, as a list of the keyfield's values in row order, as Daf.keys() does.
Every key is read into memory. To pass many keys to select_records_daf() or
delete_records() without reading them, give the SqlDaf itself: its keys are then used
in SQL. Without a keyfield, as in a Daf, the answer is an empty list.
Returns:
| Type | Description |
|---|---|
T_la
|
The keys, or an empty list if there is no keyfield. |
get_existing_keys ¶
get_existing_keys(keylist)
Keep the keys of a list that have a row, in the order of the list, as Daf.get_existing_keys() does.
The keys are looked up in SQL, all at once. Without a keyfield, the result is empty, as in a Daf.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keylist
|
T_la
|
The keys to check. |
required |
Returns:
| Type | Description |
|---|---|
T_la
|
The keys from the list that have a row. |
select_krows ¶
select_krows(krows, inverse=False, silent_error=False)
Select rows by key, as Daf.select_krows() does.
- A key, or a list or other iterable of keys, selects those rows, in the order of the keys.
This is
select_records_daf(). - A tuple of two keys selects every row from the first key to the last, both included, in row order. Either may be None, for the start or the end. A tuple of one key runs to the end.
A key range is found by the place of its keys among the rows, not by row positions. So it works on a table that has had rows deleted.
A slice is not supported. In a Daf, a slice here means row positions. Use sdaf[n:m].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
krows
|
Any
|
A key, a list of keys, or a tuple of a first and last key. |
required |
inverse
|
bool
|
If True, select the rows that are not selected. |
False
|
silent_error
|
bool
|
If True, keys that are not found are ignored. A key of a range must be found. |
False
|
Returns:
| Type | Description |
|---|---|
SqlDaf
|
A selection. |
Raises:
| Type | Description |
|---|---|
KeyError
|
A key is not found. |
NotImplementedError
|
|
TypeError
|
|
ValueError
|
There is no keyfield. |
select_records_daf ¶
select_records_daf(
keys_ls, inverse=False, silent_error=False
)
Select the rows with these keys, as Daf.select_records_daf() does.
The keys may be a list or any iterable, an in-memory Daf, or another SqlDaf of the same
database file. A SqlDaf's keys are used in SQL, as a join, so no key comes into Python. The other forms are written to a TEMP table first. The selected rows come in
the order of the keys, as in a Daf. With inverse=True, the rows whose key is not among
them, in this table's order.
A Python NULL key gives undefined results: see SqlDaf.
As in a Daf, a key that is not found raises KeyError, unless silent_error is True. That
check runs at once, as one query. The selection itself runs when first read.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keys_ls
|
Any
|
The keys: a list, an iterable, a Daf or a SqlDaf. |
required |
inverse
|
bool
|
If True, select the rows whose key is not among them. |
False
|
silent_error
|
bool
|
If True, keys that are not found are ignored. |
False
|
Returns:
| Type | Description |
|---|---|
SqlDaf
|
A selection. |
Raises:
| Type | Description |
|---|---|
KeyError
|
A key is not found, and |
ValueError
|
This SqlDaf, or a SqlDaf given as the keys, has no keyfield. |
Examples:
>>> import tempfile
>>> SqlDaf.db_path = tempfile.mkdtemp() + '/job.db'
>>> marks_daf = Daf(lol=[['b1', 1], ['b2', 0], ['b3', 1]], cols=['ballot_id', 'v'], keyfield='ballot_id')
>>> marks_sdaf = SqlDaf.from_daf(marks_daf, name='marks')
>>> marks_sdaf.select_records_daf(['b3', 'b1']).to_daf().to_lod()
[{'ballot_id': 'b3', 'v': 1}, {'ballot_id': 'b1', 'v': 1}]