【发布时间】:2011-08-02 22:43:30
【问题描述】:
我正在使用 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 实现可以比 custom-data-manipulation-on-each-row 操作更快地执行简单的 filter-group-and-sum 操作,而这足以弥补该开销。 问题是,这类 SQL 语句生成起来更复杂,因为每列出现在语句中的两个位置——一次在 fields 子句中,一次在 FROM 子句中,而不是像前两种方法那样仅在 fields 子句中.另外,我需要小心所有这些临时表的名称。
那么,有什么意见吗?
【问题讨论】: