(点击
上方公众号
,可快速关注)
英文:jooq
译者:伯乐在线 - unblock
链接:
http://blog.jobbole.com/62924/
如果一个计算应该在数据库端运行,而却没有这么做,那将是大错特错。
我们并非提倡将所有业务逻辑盲目地移到数据库,但当我在 StackOverflow 看到一个这样的问题时,就有种冲动想让你看下这篇热文—— 10 Common Mistakes Java Developers Make When Writing SQL ——中的第二点,链接是https://blog.jooq.org/2013/07/30/10-common-mistakes-java-developers-make-when-writing-sql/。
那个 stack overflow 上的问题,本质上来说是这样的:
在如下的中型表中,我想统计每个 App ID 中 status 为 0 或 1 的 doc 数
AppID
|
DocID
|
DocStatus
------+-------+----------
1
|
100
|
0
1
|
101
|
1
2
|
200
|
0
2
|
300
|
1
...
|
...
|
...
我该使用 Hibernate 吗?
答案是:不!别用 hibernate 来做(除非是写 native query),应该用 SQL 来做 。S——Q——L !使用SQL Server的话,有很多简单的做法来实现这个查询,而且时间会比将全部数据不作聚集就装到 java 内存少很多。
以 SQL Server 来举个例:
使用 GROUP BY
这是最简单的做法,但它不一定完全符合你的要求。即是,子集合不在同一行。
SELECT
[AppID],
[DocStatus],
count
(*)
FROM
[MyTable]
GROUP
BY
[AppID],
[DocStatus]
如 SQLFiddle 的例子,会查出这样的东西:
|
APPID
|
DOCSTATUS
|
COLUMN_2
|
|-------|-----------|----------|
|
1
|
0
|
2
|
|
2
|
0
|
3
|
|
1
|
1
|
3
|
|
2
|
1
|
2
|
使用 nested select
这可能就是那个特殊用户所要的效果。他们可能想每个集合分别一列,而nest select就是最通用的实现手法之一。记住这种做法在某些数据库上是有点慢的,需要花些时间制定执行计划。
SELECT
[AppID],
(
SELECT count
(*)
FROM
[MyTable]
[t2]
WHERE
[t1].[AppID]
=
[t2].[AppID]
AND
[DocStatus]
=
0)
[Status_0],
(
SELECT count
(*)
FROM
[MyTable]
[t2]
WHERE
[t1].[AppID]
=
[t2].[AppID]
AND
[DocStatus]
=
1)
[Status_1]
FROM
[MyTable]
[t1]
GROUP
BY
[AppID]
例如 SQLFiddle ,跑出这样的东西:
|
APPID
|
STATUS_0
|
STATUS_1
|
|-------|----------|----------|
|
1
|
2
|
3
|
|
2
|
3
|
2
|
使用 sum()
这可能是最佳的作法。它跟前面那个nest select一样,但只能用于简单的查询,而前者更灵活。
SELECT
[AppID],
SUM
(IIF([DocStatus]
=
0,
1,
0))
[Status_0],
SUM
(IIF([DocStatus]
=
1,
1,
0))
[Status_1]
FROM
[MyTable]
[t1]
GROUP
BY
[AppID]
例如 SQLFiddle ,结果如上。
使用 PIVOT
这种方案是为 SQL 迷而准备的。它使用了 T-SQL 的 PIVOT 子句!
SELECT
[AppID],
[0],
[1]
FROM
(
SELECT
[AppID],
[DocStatus]
FROM
[MyTable]
)
[t]
PIVOT
(
count
([DocStatus])
FOR
[DocStatus]
IN
([0],
[1])
)
[pvt]
SQL 迷就该用 PIVOT !
例如 SQLFiddle ,结果亦如上。
结论
以上建议任君选择,而且我也相信还有更多方案。它们都比基于java的聚合好几个数量级,即使是在少量数据的情况下。我们将多次重申这个观点。
正如 Gavin King 所说的:
你在使用 Hibernate,并不就意味着你把它套到所有事情上。这是我说了十几年的话了。
转为我们的说法就是:
该用 SQL 的时候就用 SQL ,它的适应性超乎你想象。
------------
------
推荐 ----------
--------
范品社推出了十几款程序员、电影、美剧和物理题材的
极客T恤
。
单件 ¥59.9、两件减¥12、四件减¥28
,详见网店商品页介绍。
网店地址:
https://fanpinshe.taobao.com/
淘口令:
复制以下红色内容,
然后打开手淘即可购买
范品社,使用¥极客T恤¥抢先预览(长按复制整段文案,打开手机淘宝即可进入活动内容)