PyQt5 QTableView实现SQLite查询结果行列转置显示
在PyQt5的QTableView中转置显示SQLite聚合查询结果(1行多列→2列多行)
刚好我之前做过类似的需求,给你分享两个比较实用的解决方案,不管是从SQL层面还是PyQt模型层处理都能搞定:
方法一:在SQL查询阶段直接转置结果
如果你的聚合查询逻辑不复杂,直接在SQL里用UNION ALL把每一列转成一行是最省心的办法,这样查询结果直接就是2列多行的格式,不用再在PyQt里做额外处理。
举个例子,假设你原本的聚合查询是:
SELECT count(*) AS total, sum(amount) AS total_amount, avg(price) AS avg_price FROM orders;
只需要改成下面的写法,就能直接得到转置后的结果:
SELECT 'total' AS stat_name, count(*) AS stat_value FROM orders UNION ALL SELECT 'total_amount' AS stat_name, sum(amount) AS stat_value FROM orders UNION ALL SELECT 'avg_price' AS stat_name, avg(price) AS stat_value FROM orders;
之后你直接用QSqlQueryModel绑定这个查询结果,设置给QTableView就可以了。这个方法的优势是直接让数据库处理转置逻辑,前端代码几乎不用改,性能也不错。
方法二:在PyQt模型层手动构造转置数据
如果不想修改原有的SQL查询,或者聚合列数量不固定(比如动态生成的查询),可以在拿到查询结果后,手动用QStandardItemModel构造转置后的模型。
下面是完整的代码示例:
from PyQt5.QtSql import QSqlQuery from PyQt5.QtGui import QStandardItemModel, QStandardItem from PyQt5.QtWidgets import QTableView # 执行原聚合查询 query = QSqlQuery("SELECT count(*) AS total, sum(amount) AS total_amount, avg(price) AS avg_price FROM orders") # 因为查询结果只有一行,直接定位到第一行 if query.first(): # 创建转置后的模型,设置表头 transposed_model = QStandardItemModel() transposed_model.setHorizontalHeaderLabels(["统计项名称", "统计值"]) # 遍历原查询的所有列,把列名和对应值添加为模型的一行 for col_idx in range(query.record().count()): # 第一列:原列名 name_item = QStandardItem(query.record().fieldName(col_idx)) # 第二列:对应的值(转成字符串避免类型问题) value_item = QStandardItem(str(query.value(col_idx))) # 添加到模型中 transposed_model.appendRow([name_item, value_item]) # 把模型绑定到QTableView table_view = QTableView() table_view.setModel(transposed_model) table_view.show()
这个方法的好处是灵活性高,不管原查询有多少列,都能自动遍历处理,而且可以方便地对模型做额外的定制(比如设置单元格不可编辑、调整对齐方式等)。
内容的提问来源于stack exchange,提问作者CodingCat
相关产品推荐
相关产品推荐

