我有一张包含姓名、年份和分数/计数的表格:
("Andi", 2020, 40),
("Andi", 2021, 60),
("Andi", 2022, 55),
("Andi", 2023, 55),
("Alex", 2020, 14),
("Alex", 2021, 1),
("Alex", 2022, 13),
("Alex", 2023, 13),
...
我尝试使用 writefile() 等将其压缩到 Excel 文件中。 它应该看起来像这样
姓名 | 2020 | 2021 | 2022 | 2023 | 总计 |
---|---|---|---|---|---|
安迪 | 40 | 60 | 55 | 55 | 210 |
亚历克斯 | 14 | 1 | 13 | 13 | 41 |
ofc 明年他们将添加新记录: (“安迪”,2024,49),(“亚历克斯”,2024,10),... 因此,当我明年再次重新创建 Excel 文件时,sqlstament 也应该添加。 我发现了这个: 如何在SQL表中以条件选择列值作为列名 这是硬编码的,可以按照我想要的方式工作,但我不想每年都改变它。 我的数据库也是从 2016 年开始的,所以这将是一个很长的声明。 我尝试为 select、from、on 制作 for 循环,但我认为可能有更简单的方法?
我有什么想法可以实现这一目标吗? 谢谢你
您可以使用如下所示的 SQL 查询将列名称旋转为年份。
SELECT name,
MAX(CASE WHEN year = 2020 THEN score END) AS '2020',
MAX(CASE WHEN year = 2021 THEN score END) AS '2021',
MAX(CASE WHEN year = 2022 THEN score END) AS '2022',
MAX(CASE WHEN year = 2023 THEN score END) AS '2023',
MAX(CASE WHEN year = 2024 THEN score END) AS '2024',
COALESCE(MAX(CASE WHEN year = 2020 THEN score END), 0)+COALESCE(MAX(CASE WHEN year = 2021 THEN score END), 0)+COALESCE(MAX(CASE WHEN year = 2022 THEN score END), 0)+COALESCE(MAX(CASE WHEN year = 2023 THEN score END), 0)+COALESCE(MAX(CASE WHEN year = 2024 THEN score END), 0) AS total
FROM scores
GROUP BY name
ORDER BY name;
这可以在添加新的年份时动态生成。
# Get all the years
cursor.execute("SELECT DISTINCT year FROM scores ORDER BY year")
years = cursor.fetchall()
# Generate the pivot columns as years
columns = []
for year in years:
columns.append(f"MAX(CASE WHEN year = {year[0]} THEN score END) AS '{year[0]}'")
columns_str = ", ".join(columns)
sql = f"""
SELECT name, {columns_str},
{"+".join([f"COALESCE(MAX(CASE WHEN year = {year[0]} THEN score END), 0)" for year in years])} AS total
FROM scores
GROUP BY name
ORDER BY name;
"""
cursor.execute(sql)
result = cursor.fetchall()
df = pd.DataFrame.from_records(result, columns=['name'] + [str(year[0]) for year in years] + ['total'])
print(df)
输出
name 2020 2021 2022 2023 2024 total
0 Alex 14 1 13 13 10 51
1 Andi 40 60 55 55 49 259