[英]function to reduce redundancy for reading database in sqlite3
大家好:)我是编程新手,想在创建 function 以帮助减少代码中的冗余方面寻求帮助。 我已经成功创建了一个数据库,其中包含 5 个不同国家的数据表。 所有表格都具有相同的结构(请参阅随附的屏幕截图以供参考)。 我的目标是针对特定参数(污染类型)计算所有不同表中所有行的总和。 我已经设法仅将代码写入 select 我需要一个国家的特定数据(我尝试编写代码来计算总和但我无法弄清楚,所以我决定只使用 select 数据,然后自己手动计算值用计算器 - 我知道这有点违背编程的目的,但在我的编程水平(初学者)我觉得这是我可以编写代码的唯一方法)我的问题是我有五个国家,所以我不想为不同的国家重复相同的代码块。 这是我对一个国家的代码:
def read_MaltaData():
conn = sqlite3.connect('FinalProjectDatabase.sqlite3')
Malta = conn.cursor()
Malta.execute("SELECT * FROM MaltaData WHERE AirPollutant = 'PM10'")
result = Malta.fetchall()
print(result)
我的结果是这样的:
[('Malta', 'Valletta', 'MT00005', 'Msida', 'PM10', 64.3, 'ug/m3', 'Traffic', 'urban', 14.489985999999998, 35.895835999489535, 2.0), ('Malta', None,
等。
(我将手动计算我需要的数据 - 在本例中为 64.3 + 下一行的值 - 因为我不知道如何在 python 中执行此操作)
澄清一下,我的目标不是将所有表格的总和作为一个整体值(即我不想将所有国家的值加在一起)。 我想要的 output 应该是这样的:
Malta summation value
italy summation value
france summation value
而不是这样
国家加在一起 = 一个整数(即所有总和值加在一起)
我将非常感谢我能得到的任何帮助。 不幸的是,我无法与您共享数据库,这就是为什么我要共享它的屏幕截图。
您可以使用 UNION ALL 为每个国家/地区获取一行:
SELECT 'France' country, SUM(AirPolutionLevel) [summation value] FROM FranceData WHERE AirPollutant = 'PM10'
UNION ALL
SELECT 'Germany' country, SUM(AirPolutionLevel) [summation value] FROM GermanyData WHERE AirPollutant = 'PM10'
UNION ALL
SELECT 'Italy' country, SUM(AirPolutionLevel) [summation value] FROM ItalyData WHERE AirPollutant = 'PM10'
UNION ALL
SELECT 'Malta' country, SUM(AirPolutionLevel) [summation value] FROM MaltaData WHERE AirPollutant = 'PM10'
UNION ALL
SELECT 'Poland' country, SUM(AirPolutionLevel) [summation value] FROM PolandData WHERE AirPollutant = 'PM10'
如果将国家名称作为参数传递给数据检索 function,则可以动态生成表名(注意execute
和print
中的f 字符串arguments):
def print_CountryData(country):
conn = sqlite3.connect('FinalProjectDatabase.sqlite3')
cur = conn.cursor()
cur.execute(f"SELECT SUM(AirPollutionLevel) FROM {country}Data WHERE AirPollutant = 'PM10'")
sumVal = cur.fetchone()[0]
print(f"{country} {sumVal}")
# example call:
for country in ('France', 'Germany', 'Italy', 'Malta', 'Poland'):
print_CountryData(country)
虽然出于安全原因,在sqlite3 文档中不鼓励使用简单的字符串函数构建您自己的查询字符串,但在您完全控制实际 arguments 的情况下,我认为它是安全的。
这个答案改编了forpas给出的好答案的总和,但拒绝将重复移动到SQL。 它还显示了与 python 和 output 格式的集成。
这是我的第一个答案的改进版本,已转换为最小的、可重现的示例,并与 output 结合使用。 此外,还进行了一些性能改进,例如只打开一次数据库。
import sqlite3
import random # to simulate actual pollution values
# Countries we have data for
countries = ('France', 'Germany', 'Italy', 'Malta', 'Poland')
# There is one table for each country
def tableName(country):
return country+'Data'
# Generate minimal version of tables filled with random data
def setup_CountryData(cur):
for country in countries:
cur.execute(f'''CREATE TABLE {tableName(country)}
(AirPollutant text, AirPollutionLevel real)''')
for i in range(5):
cur.execute(f"""INSERT INTO {tableName(country)} VALUES
('PM10', {100*random.random()})""")
# Get sum up pollution data for each country
def print_CountryData(cur):
for country in countries:
cur.execute(f"""SELECT SUM(AirPollutionLevel) FROM
{tableName(country)} WHERE AirPollutant = 'PM10'""")
sumVal = cur.fetchone()[0]
print(f"{country:10} {sumVal:9.5f}")
# For testing, we use an in-memory database
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
setup_CountryData(cur)
# The functionality actually required
print_CountryData(cur)
样品 output:
France 263.79430
Germany 245.20942
Italy 225.72068
Malta 167.72690
Poland 290.64190
如果不实际尝试,通常很难评估解决方案。 这就是为什么 StackOverflow 上的提问者经常被鼓励以这种方式提问的原因:它使人们更有可能理解并解决问题......快速
如果数据库不是太大,您可以使用pandas
。
这种方法比直接使用 SQL 查询效率低,但如果您想在笔记本中以交互方式探索数据,则可以使用这种方法。
您可以使用 pandas.read_sql_query 从 SQLite 数据库创建pandas.read_sql_query
然后使用专为此类任务设计的pandas.DataFrame
方法执行计算。
对于您的具体情况:
import sqlite3
import pandas as pd
conn = sqlite3.connect(db_file)
query = "SELECT * FROM MaltaData WHERE AirPollutant = 'PM10'"
df = pd.read_sql_query(query, conn)
# check dataframe content
print(df.head())
如果我理解,然后您想计算给定列中值的总和:
s = df['AirPollutionLevel'].sum()
如果您有缺失值,您可能希望在求和之前用 0 填充它们:
s = df['AirPollutionLevel'].fillna(0).sum()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.