在SQLite中执行数据透视表的最佳方法是什么?

时间:2011-08-02 22:43:30

标签: c# sql sqlite pivot

我正在使用C#和SQLite来分割大量数据,我经常需要以数据透视表的形式显示我的数据。我可以通过使用C#从另一个查询创建SQL命令来轻松地使我的枢轴动态化,但是我仍然无法决定使用哪种方式进行旋转,所以我希望听到一些关于这个问题的程序员的意见。我..

我有三种方法。假设我们有一个名为tData的简单表,有三列:“row”表示该数据的行号,“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子句中。另外,我需要小心所有临时表的名称。

那么,有什么意见吗?

2 个答案:

答案 0 :(得分:1)

我希望case语句方法比对表执行尽可能多的groupbys-and-join更快地执行,因为在列中有不同的值。前者是CPU密集型,后者是磁盘密集型。例如。如果要成为列标题的列值包含一周中的某一天,则您将拥有七个数据透视列和七个选择组。那可能很贵;这将取决于桌子的大小。

答案 1 :(得分:0)

看起来您正在使用EAV设计,这使得必须将行转移到列中。在适当的关系数据库设计中,您不会使用EAV。列将是列,您不需要转动。

也就是说,我知道EAV有时候是邪恶中的较小者,当需要在数据库中存储“可扩展”属性集时,它是一种流行的设计。

获取数据的最有效方法是忘记在SQL中执行数据透视。只需将每个给定值row

的多个行提取属性
SELECT row, col, val FROM tData WHERE row = ...

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

这有以下优点:

  • 查询很简单。只有三列要在select-list中命名,不需要列别名。
  • 查询对于RDBMS执行来说是便宜的。没有GROUP BY,没有自我加入等等。
  • 仍然支持EAV设计的可扩展优势。事实上,它更容易扩展,因为当您向数据中添加新的逻辑列时,您不必重写SQL查询。
相关问题