java中rdbms
使用RDBMS时,您可能会做一件事完全错误。 而且,当您应该这样做时,事情并没有在数据库中运行您的计算。
我们不主张盲目地将所有业务逻辑移到数据库中,但是当我看到类似这样的Stack Overflow问题时 ,我感到很想轻轻地提醒您我们Java开发人员在编写SQL时常犯的10个常见错误中的第二项。 。
堆栈溢出问题基本上可以归结为以下问题(自由引用):
从下面的中型表中,我希望对每个应用程序ID计数状态为0或1的文档数:
AppID | DocID | DocStatus ------+-------+---------- 1 | 100 | 0 1 | 101 | 1 2 | 200 | 0 2 | 300 | 1 ... | ... | ...
我应该为此使用Hibernate吗?
答案是: 不! 不要为此使用Hibernate(除非您是指本机查询)。 您应该为此使用SQL 。 Es-Queue-El! 如果要在汇总之前将所有数据加载到Java内存中,只需花费很少的时间,SQL Server就有许多琐碎的选项可以帮助您运行此查询!
例如(使用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 |
使用嵌套选择
这可能是该特定用户正在寻找的解决方案。 他们可能希望将每种聚合放在单独的列中,而一种非常通用的方法是使用嵌套选择。 请注意,在某些难以优化这些内容的数据库中,此解决方案可能会证明有些慢
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()
此解决方案可能是最佳解决方案。 尽管它仅适用于简单查询,但它等效于前一个带有嵌套选择的版本,而嵌套选择版本则更为通用。
SELECT [AppID],
SUM(IIF([DocStatus] = 0, 1, 0)) [Status_0],
SUM(IIF([DocStatus] = 1, 1, 0)) [Status_1]
FROM [MyTable] [t1]
GROUP BY [AppID]
使用PIVOT
该解决方案是针对自己SQL Aficionados的。 它使用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
结论
您可以在上述建议中自由选择武器,我敢肯定还有更多选择。 所有这些都将比任何基于Java的聚合实现都要好几个数量级,即使对于很小的数据集也可以肯定。 我们会一次又一次地说,并且我们会一遍又一遍地引用Gavin King :
仅仅因为您在使用Hibernate,并不意味着您必须在所有方面都使用它。 我已经提出了大约十年的观点。
用我们的话说:
适当时使用SQL! 这比您想像的要多得多!
翻译自: https://www.javacodegeeks.com/2014/03/please-run-that-calculation-in-your-rdbms.html
java中rdbms