根据投影从同一列中减去值
Subtract value from same column based on projection
我有一个信用变动模式,如下所示:
id | orderno | due | bookingdate | movementtype
=================================================
1 | o11 | 30.50 | 10.01.2017 | CREDIT
2 | o22 | 50.99 | 11.01.2017 | DEBIT
3 | o11 | 20.40 | 12.01.2017 | DEBIT
4 | o22 | 77.88 | 13.01.2017 | CREDIT
5 | o11 | 05.20 | 14.01.2017 | DEBIT
我想检索给定订单号和年份的 CREDIT 减去 DEBIT 的总和。
所以对于上面的虚拟数据,传递 orderno=o11
和 booking=2017
,我希望 4.9
.
我提出了一个包含两个子查询的查询:
SELECT
(credit - debit) AS total
FROM
(
SELECT
COALESCE(SUM(due), 0.0) AS credit
FROM
accountactivity
WHERE
orderno = :ordernoParam
AND YEAR(bookingdate) = :bookingParam
AND movementtype = 'CREDIT'
),
(
SELECT
COALESCE(SUM(due), 0.0) AS debit
FROM
accountactivity
WHERE
orderno = :ordernoParam
AND YEAR(bookingdate) = :bookingParam
AND movementtype = 'DEBIT'
)
问题:是否可以针对我的任务优化查询?出于性能原因,我想避免子查询。它应该适用于 DB2 和 Oracle 11g,可以通过本机查询,或者最好是通过 HibernateQL。
我会用CASE
SELECT
COALESCE(SUM(CASE WHEN movementtype = 'CREDIT' THEN due END), 0.0) -
COALESCE(SUM(CASE WHEN movementtype = 'DEBIT' THEN due END), 0.0) AS total
FROM
accountactivity
WHERE
orderno = :ordernoParam
AND YEAR(bookingdate) = :bookingParam
如果您的覆盖索引 accountactivity(orderno)
包括 bookingdate
、movementtype
和 due
属性,则应通过一次范围扫描执行它。
另一个可以优化的问题是YEAR(bookingdate) = :bookingParam
条件。查询处理器不能使用它通过索引中的查找操作进行搜索。如果您将其重写为 bookingdate >= CAST('1.1.' + :bookingParam AS DATE) and bookingdate <= CAST('31.12.' + :bookingParam AS DATE)
之类的内容(这可能是特定于 DBMS 的),那么您可以拥有一个包含 movementtype
和 due
属性的索引 accountactivity(orderno, bookingdate)
并且范围扫描将读取仅相关行。
我有一个信用变动模式,如下所示:
id | orderno | due | bookingdate | movementtype
=================================================
1 | o11 | 30.50 | 10.01.2017 | CREDIT
2 | o22 | 50.99 | 11.01.2017 | DEBIT
3 | o11 | 20.40 | 12.01.2017 | DEBIT
4 | o22 | 77.88 | 13.01.2017 | CREDIT
5 | o11 | 05.20 | 14.01.2017 | DEBIT
我想检索给定订单号和年份的 CREDIT 减去 DEBIT 的总和。
所以对于上面的虚拟数据,传递 orderno=o11
和 booking=2017
,我希望 4.9
.
我提出了一个包含两个子查询的查询:
SELECT
(credit - debit) AS total
FROM
(
SELECT
COALESCE(SUM(due), 0.0) AS credit
FROM
accountactivity
WHERE
orderno = :ordernoParam
AND YEAR(bookingdate) = :bookingParam
AND movementtype = 'CREDIT'
),
(
SELECT
COALESCE(SUM(due), 0.0) AS debit
FROM
accountactivity
WHERE
orderno = :ordernoParam
AND YEAR(bookingdate) = :bookingParam
AND movementtype = 'DEBIT'
)
问题:是否可以针对我的任务优化查询?出于性能原因,我想避免子查询。它应该适用于 DB2 和 Oracle 11g,可以通过本机查询,或者最好是通过 HibernateQL。
我会用CASE
SELECT
COALESCE(SUM(CASE WHEN movementtype = 'CREDIT' THEN due END), 0.0) -
COALESCE(SUM(CASE WHEN movementtype = 'DEBIT' THEN due END), 0.0) AS total
FROM
accountactivity
WHERE
orderno = :ordernoParam
AND YEAR(bookingdate) = :bookingParam
如果您的覆盖索引 accountactivity(orderno)
包括 bookingdate
、movementtype
和 due
属性,则应通过一次范围扫描执行它。
另一个可以优化的问题是YEAR(bookingdate) = :bookingParam
条件。查询处理器不能使用它通过索引中的查找操作进行搜索。如果您将其重写为 bookingdate >= CAST('1.1.' + :bookingParam AS DATE) and bookingdate <= CAST('31.12.' + :bookingParam AS DATE)
之类的内容(这可能是特定于 DBMS 的),那么您可以拥有一个包含 movementtype
和 due
属性的索引 accountactivity(orderno, bookingdate)
并且范围扫描将读取仅相关行。