繁体   English   中英

在SQLite中做数据透视表的最佳方法?

[英]Best way to do a pivot table in SQLite?

我正在使用C#和SQLite切片大量数据,并且我经常需要以数据透视表形式显示数据。 通过使用C#从另一个查询创建SQL命令,我可以轻松地使数据透视图动态化,但是我仍然无法决定采用哪种方法进行数据透视图本身,因此我想从经验丰富的程序员那里听到一些意见。我..

我想到了三种方法。 假设我们有一个名为tData的简单表,该表具有三列:“行”代表该数据的行号,“ col”代表列号,“ val”代表值。

正统的方法是使用CASE表达式:

SELECT
      row,
      sum(CASE col WHEN 1 THEN val END) AS col1,
      sum(CASE col WHEN 2 THEN val END) AS col2,
      sum(CASE col WHEN 3 THEN val END) AS col3
FROM tData
GROUP BY row

但是,我在想,如果我放弃CASE语句并直接在值上使用逻辑表达式,并利用true == 1和false == 0的事实,可能会更快:

SELECT
      row,
      sum((col=1)*val) AS col1,
      sum((col=2)*val) AS col2,
      sum((col=3)*val) AS col3
FROM tData
GROUP BY row

我怀疑这种方法应该更快,因为CASE表达式应该有一些开销,但是我不确定。

第三种方法稍微复杂一点:它使用JOIN进行透视:

SELECT
      rows.row,
      col1.valSum AS col1,
      col2.valSum AS col2,
      col3.valSum AS col3
FROM
    (SELECT row FROM tData GROUP BY row) AS rows
LEFT JOIN
    (SELECT row,sum(val) AS valSum FROM tData WHERE col=1 GROUP BY row) AS col1
    ON rows.row=col1.row
LEFT JOIN
    (SELECT row,sum(val) AS valSum FROM tData WHERE col=2 GROUP BY row) AS col2
    ON rows.row=col2.row
LEFT JOIN
    (SELECT row,sum(val) AS valSum FROM tData WHERE col=3 GROUP BY row) AS col3
    ON rows.row=col3.row

的确,那些JOIN的开销很大,但是根据我在处理大型表时的有限经验,SQL实现可以比每行自定义数据操作快得多的速度执行简单的过滤器组和求和操作,并且弥补了这些开销。 问题在于,这类SQL语句的生成更加复杂,因为每一列都出现在语句的两个位置上-一次出现在fields子句中,一次出现在FROM子句中,而不是像前两种方法那样仅出现在fields子句中。 另外,我需要小心所有这些临时表的名称。

那么,有什么意见吗?

我希望case语句方法的执行速度比对表进行的groupbys-joins更快,因为在问题列中有不同的值。 前者是CPU密集型,后者是磁盘密集型。 例如,如果要成为列标题的列值包含一周中的某一天,则您将有七个枢轴列和七个selects-groupbys。 那可能很昂贵; 这将取决于表的大小。

看起来您正在使用EAV设计,这有必要将行旋转为列。 在适当的关系数据库设计中,您不会使用EAV。 列就是列,您不需要旋转。

就是说,我了解到,EAV有时不那么邪恶,当需要在数据库中存储一组“可扩展”属性时,它是一种流行的设计。

取回数据的最有效方法是忘记执行SQL中的枢轴操作。 只需根据row给定值将属性作为多行获取:

SELECT row, col, val FROM tData WHERE row = ...

然后在您的C#应用​​程序中编写代码,以循环遍历所得的多行结果集。 为每个不同的row创建一个新对象。 将对象的col字段设置为val 然后继续获取查询结果的下一行。

这具有以下优点:

  • 该查询易于编写。 选择列表中仅需命名三列,无需列别名。
  • 对于RDBMS执行该查询是廉价的。 没有GROUP BY ,没有自我加入,等等。
  • 仍然支持EAV设计的可扩展优势。 实际上,扩展起来更容易,因为在向数据添加新的逻辑列时,不必重写SQL查询。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM