【问题标题】:Include data from another row in in the same table with sqlalchemy query使用 sqlalchemy 查询在同一个表中包含另一行的数据
【发布时间】:2020-06-04 20:56:58
【问题描述】:

我有一个表 (SQLite),其中包含以下格式的数据行:

+--------------------------------------------------------------------------------+
|    ID    |      start       |        end       |    type_id    |    user_id    |
+----------+------------------+------------------+---------------+---------------+
|    1     | 2020-01-01 17:00 | 2020-01-02 05:00 |       1       |       10      |
|    2     | 2020-01-01 17:00 | 2020-01-02 05:00 |       1       |       9       |
|    3     | 2020-01-02 02:00 | 2020-01-02 03:00 |       2       |       10      |

我想编写一个 sqlalchemy 查询(虽然不是 Flask-sqlalchemy),它可以找到 type_id=1 所在的所有数据,然后还找到与 type_id=2 同时出现的那些 type_id=1并返回该行的所有信息以及匹配的type_id=1 的开头。

例如,假设第 1 行和第 3 行同时发生,并且是同一用户,我想返回以下内容:

[
  {"ID":1, "start":"2020-01-01 17:00", "end":"2020-01-02 05:00", "type_id":1, "user_id":10},
  {"ID":3, "start":"2020-01-02 02:00", "end":"2020-01-02 03:00", "type_id":2, "user_id":10, "date":"2020-01-01"}
]

我愿意添加一个额外的“组”列,我可以确保同时发生的具有相同 user_id 的事物在添加时具有相同的组 id,但仍然可以查询到在没有暴力 for 循环的情况下通过一两个查询获得所有这些?

目前,我能想到的唯一方法是首先查询所有type_id=1,然后查询所有类型 ID=3,然后为每个类型运行一个返回开始日期的新查询另一个匹配的行。像这样的:

type_1s=db.query(TABLE).filter(TABLE.start>=some_input_date, TABLE.end<=some_input_date, TABLE.type_id==1)

然后

type_2s=db.query(TABLE).filter(TABLE.start>=some_input_date, TABLE.end<=some_input_date, TABLE.type_id==2)
for row in type_2s:
  #run a new query in here to find rows where the user_id matches the dates overlap and the type_id is 1.

然后我可以连接这两个列表,以确保那些 type_id=2 的列表与适当的 type_id=1 正确分组在一起。

如果有人有任何建议,一个更好的解决方案是通过一个查询来生成以下数据集:

{
  "2020-01-01":[
    {10:[
          {"ID":1, "start":"2020-01-01 17:00", "end":"2020-01-02 05:00", "type_id":1, "user_id":10},
          {"ID":3, "start":"2020-01-02 02:00", "end":"2020-01-02 03:00", "type_id":2, "user_id":10}
        ],
     9:[
         {"ID":2, "start":"2020-01-01 17:00", "end":"2020-01-02 05:00", "type_id":1, "user_id":9,
       ],
    }
  ],

【问题讨论】:

  • 使用 sqlalchemy.orm 中的别名选项可能会有解决方案。我可以为同一个表设置一个别名,然后添加一组过滤器来获取用户和日期要求的 type_id=2 的过滤器,然后再添加一个过滤器来抓取 type_id 1 的开始组件,它限制了开始和结束type_id 3的时间。

标签: mysql python-3.x sqlalchemy


【解决方案1】:

解决方案是包含TABLE 的别名版本,然后添加一个额外的过滤器,使用如下:

from sqlalchemy.orm import aliased

MATCH=aliased(TABLE)

db.query(
  TABLE,
  MATCH.start.label('date') # <-- this renames what would be the same column name
).filter(
  TABLE.start>=some_input_date,
  TABLE.end<=some_input_date,
  TABLE.type_id==2
).filter(
  MATCH.start<=TABLE.start,
  MATCH.end>=TABLE.end,
  MATCH.user_id==TABLE.user_id,
  MATCH.type_id==1
)

这给出了 type_id 2 的列表,包括它们所属的日期。 虽然它仍然意味着有一个两步解决方案(首先获取类型 1,然后获取类型 2),但它至少避免了通过 for 循环执行许多单独查询的蛮力方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多