我有一些时间序列数据,其中有时间序列集,每个时间序列的Timeseries
实例都具有一对多关系
与Point
个实例。以下是数据的简化表示。
tables.py:
class Timeseries(Base):
__tablename__ = "timeseries"
id = Column("id", Integer, primary_key=True)
points = relationship("Point", back_populates="ts")
class Point(Base):
__tablename__ = "point"
id = Column("id", Integer, primary_key=True)
t = Column("t", Float)
v = Column("v", Float)
ts_id = Column(Integer, ForeignKey("timeseries.id"))
ts = relationship("Timeseries", back_populates="points")
问题:我正在尝试使用以下列进行查询:“ timeseries_id”,“ id”,“ t”,“ v”,“ id_next”,“ t_next” ”,“ v_next”。也就是说,我希望能够按时间顺序查看时间序列中每个点的数据以及下一个点的数据,但是我一直在努力获取一个表,该表是否不包含来自隐式联接的元素? (编辑:重要的一点是,我希望能够使用sqlalchemy中的100%查询和子查询对象来获得此列表,因为我需要在进一步的联接,过滤器等中使用此查询表。)这是基本内容我得到了(请注意,由于这是我的实际数据库的简化版本,所以我没有运行此代码,但这是相同的想法):
# The point data actually in the database.
sq = (session.query(
Timeseries.id.label("timeseries_id"),
Point.id,
Point.t,
Point.v)
.select_from(
join(Timeseries, Point, Timeseries.id==Point.ts_id))
.group_by('timeseries_id')
.subquery())
# first point manually added to each list in query
sq_first = (session.query(
Timeseries.id.label("timeseries_id"),
sa.literal_column("-1", Integer).label("id"), # Some unused Point.id value
sa.literal_column(-math.inf, Float).label("t"),
sa.literal_column(-math.inf, Float).label("v"))
.select_from(
join(Timeseries, Point, Timeseries.id==Point.ts_id))
.subquery())
# last point manually added to each list in query.
sq_last = (session.query(
Timeseries.id.label("timeseries_id"),
sa.literal_column("-2", Integer).label("id"), # Another unused Point.id value
sa.literal_column(math.inf, Float).label("t"),
sa.literal_column(math.inf, Float).label("v"))
.select_from(
join(Timeseries, Point, Timeseries.id==Point.ts_id))
.subquery())
# Append each timeseries in `sq` table with last point
sq_points_curr = session.query(sa.union_all(sq_first, sq)).subquery()
sq_points_next = session.query(sa.union_all(sq, sq_last)).subquery()
假设到目前为止我所做的事情很有用,这就是我遇到的问题:
#I guess rename the columns in `sq_points_next` to append them by "_next"....
sq_points_next = (session.query(
sq_points_curr.c.timeseries_id
sq_points_curr.c.id.label("id_next"),
sq_points_curr.c.t.label("t_next"),
sq_points_curr.c.v.label("v_next"))
.subquery())
# ... and then perform a join along "timeseries_id" somehow to get the table I originally wanted...
sq_point_pairs = (session.query(
Timeseries.id.label("timeseries_id")
"id",
"t",
"v",
"id_next",
"t_next",
"v_next"
).select_from(
sq_points, sq_points_next, sq_points.timeseries_id==sq_points_next.timeseries_id)
)
我什至不确定这最后一个函数是否会在此时编译,因为它还是根据实际代码进行了改编/简化,但是它不会产生相邻时间点的表格,等等。
答案 0 :(得分:1)
假设您可以使用最新版本的sqlite3 python模块(例如,使用Anaconda),则可以使用LEAD
窗口函数来实现您的目标。为了在进一步的查询中使用LEAD
函数的结果,您还需要使用CTE。以下方法适用于您提供的模式:
sq = session.query(
Timeseries.id.label("timeseries_id"),
Point.id.label("point_id"),
Point.t.label("point_t"),
Point.v.label("point_v"),
func.lead(Point.id).over().label('point_after_id'),
func.lead(Point.v).over().label('point_after_v'),
func.lead(Point.t).over().label('point_after_t')).select_from(
join(Timeseries, Point, Timeseries.id == Point.ts_id)).order_by(Timeseries.id)
with_after = sq.cte()
session.execute(with_after.select().where(
with_after.c.point_v < with_after.c.point_after_v)).fetchall()
答案 1 :(得分:0)
为什么不直接检索与特定points
行相关的所有Timeseries
数据,然后将其重新组合为一个索引,而不是跳过获取所需的配对结果的查询您正在寻找的对?例如:
from operator import attrgetter
def to_dict(a, b):
# formats a pair of points rows into a dict object
return {
'timeseries_id': a.ts_id,
'id': a.id, 't': a.t, 'v': a.v,
'id_next': b.id, 't_next': b.t, 'v_next': b.v
}
def timeseries_pairs(session, ts_id):
# queries the db for particular Timeseries row, and combines points pairs
ts = session.query(Timeseries).\
filter(Timeseries.id == ts_id).\
first()
ts.points.sort(key=attrgetter('t'))
pairs = [to_dict(a, b) for a, b in zip(ts.points, ts.points[1:])]
last = ts.points[-1]
pairs.append({
'timeseries_id': last.ts_id,
'id': last.id, 't': last.t, 'v': last.v,
'id_next': None, 't_next': None, 'v_next': None
})
return pairs
# pass the session and a timeseries id to return a list of points pairs
timeseries_pairs(session, 1)