【问题标题】:Getting a confusingly complicated mysql request work得到一个令人困惑的复杂 mysql 请求工作
【发布时间】:2019-12-09 15:34:59
【问题描述】:

我不是 SQL 专家,但我最近开始在 Python 中将 sqlite3 模块与数据库一起使用,并与 pandas 及其 read_sql_query() 一起使用它们是一个非常好的工具。

现在,比如说,我有一个看起来像这样的数据库(我只是为了演示目的而编造的)。

age iq  married
===============
91  77  0
54  124 1
31  124 0
32  95  0
74  34  0
18  56  0
43  42  0
78  56  0
91  77  1

任务是,这可能会有点令人困惑。我想选择与married=1(包括已婚人士本身)具有相同智商的所有行(人)。所以我希望结果看起来像这样:

age iq  married
===============
91  77  0
54  124 1
31  124 0
91  77  1

即使在一般情况下,假设我的限制更加严格,并且想要选择所有与已婚者具有相同 iqage 的人。在这种情况下,结果将如下所示:

age iq  married
===============
54  124 1
91  77  0
91  77  1

可能有大量其他列可以忽略或不能忽略。

现在我当然可以迭代地这样做,首先选择已婚的,然后比较 (age,iq) 的元组,但这有点无聊。问题是,有没有一种巧妙的方法可以用pandas.read_sql_query() 一次性完成?

所以简而言之,我正在尝试做这样的事情(我知道这只是选择已婚的,但这只是一个例子):

import sqlite3
import pandas as pd

connection = sqlite3.connect('people.db')
mydata = pd.read_sql_query(
                """
                SELECT *
                from People
                    WHERE married=1 ... *some magic here*
                    GROUP BY *foo*
                    HAVING *bar*
                """, connection)

我真的无法想出任何“魔法”来让它做我想做的事情(可能是因为对所有 SQL 命令和条件了解不足)。也许有一种方法可以使用嵌套的SELECT 命令和一些类似IN 的东西来做到这一点,但我不太确定。

我觉得必须有一个简单的方法(或者我错了,迭代起来更容易),所以我问社区!

【问题讨论】:

  • 我建议您提供一个更能代表您的实际用例的示例。
  • 老实说,基本上就是这样,但是数据库中有几 GB 并且我需要比较三个标准,而不是一两个。说,ageiqdob,我认为这真的没那么重要。

标签: python mysql sql pandas sqlite


【解决方案1】:

一种方法是在 WHERE 子句中使用 EXISTS 条件,该条件断言给定的 IQ 值与至少一个其他已婚记录匹配:

SELECT age, iq, married
FROM People p1
WHERE EXISTS (SELECT 1 FROM People p2 WHERE p1.iq = p2.iq AND p2.married = 1);

Demo

使用以下索引,EXISTS 子查询的性能可能会更好:

CREATE INDEX idx ON People (iq, married);

这将允许在表中快速查找给定的iq 值,同时检查married status.m

【讨论】:

  • 太酷了!效果很好。你能解释一下from People p1 然后select 1 是什么意思吗?是不是像[x for x in range(10)] 这样的循环?或者你可以直接让我找到一个合适的术语来谷歌了解更多相关信息?
  • 您可以从阅读this tutorial 开始。对于每个人,存在逻辑检查是否可以找到另一个具有 same IQ 且已婚的人。如果是,则将此记录添加到结果集中。并不是说EXISTS 通常比WHERE IN 性能更高。
  • 好吧,我想我明白了。我得到了选择和比较的逻辑,我只是​​不知道你可以通过嵌套SELECT-s 来创建子集。谢谢!感谢您的教程,将阅读更多相关内容:)
  • 哎呀,这在我的真实数据上实际上非常慢(可能是因为它是一个嵌套循环)。但无论如何,谢谢,因为它似乎有效)
  • (iq, married) 上添加索引应该会有所帮助:CREATE INDEX idx ON People (iq, married)
【解决方案2】:

试试这个查询:

select * from People
where iq in (
    select iq from People
    group by iq
    having sum(married) > 0
)

【讨论】:

  • 这很聪明。 :) 但实际上我有一个稍微复杂的数据,其中sum(married) 之类的东西不起作用。不过,在这种情况下完美无缺。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-28
  • 1970-01-01
  • 1970-01-01
  • 2017-02-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多