如何在 sql 服务器中解决此查询?
How can I solve this query in sql server?
我有这个 table 结构:
CREATE TABLE IF NOT EXISTS `client` (
`id` int(6) unsigned NOT NULL,
`name` varchar(200),
`balance` decimal NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `client` (`id`, `name`, `balance`) VALUES
('1', 'Pepito', '500');
CREATE TABLE IF NOT EXISTS `balance_Movements` (
`id` int(6) unsigned NOT NULL,
`clientId` int(6),
`movementType` varchar(200),
`import` decimal NOT NULL,
`dateMovement` datetime,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `balance_Movements` (`id`, `clientid`, `movementType`, `import`, `dateMovement`) VALUES
('1', '1', 'payment', '50', '2018/05/11'),
('2', '1', 'refund', '25.05', '2018/05/10'),
('3', '1', 'refund', '60', '2018/04/06'),
('4', '1', 'payment', '100', '2018/04/03');
客户开始时有:500€ --> 所以声明变量将是这样的:
declare @total_balance as decimal;
set @total_balance = (select balance from client where id = 1);
Result
------
500
我需要在@total_balance的结果后进行更改,取最后一行的值:
示例:
Table_balance_Movements
------------------------
Total
-----
450
475.05
535.05
435.05
解释:
450 -->客户端是500开头的,所以如果movement类型是payment我需要把client的balance减去import movement,保存数据在 @total_balance 中,稍后使用 = 500 - 50 = 450
475.05 --> 我得到了 @total_balance 的值和 25.05 的总和,因为在这一行中,移动类型是 refund = 450 + 25.05 = 475.05
535.05 --> 同样的事情,我从 @total_balance 变量中获取值并查看移动的类型并减去或求和 import = 475.05 + 60 = 535.05
435.05 --> 535.05 - 100 = 435.05
我想做类似这个概念的东西:
declare @total_balance as decimal;
set @total_balance = (select balance from client where id = 1);
select (case when movementType = 'payment' then (@total_balance = @total_balance - import)
when movementType = 'refund' then (@total_balance = @total_balance + import) end) as total
from balance_Movements;
有可能吗?谢谢
您可以使用累加和 window 函数解决此问题。以下将在 SQL 服务器和 MySQL 8+
中工作
select c.*,
(c.balance +
sum(case when bm.movement_type = 'payment' then - import
when bm.movement_type = 'refund' then import
end) over (partition by c.id order by bm.datemovement)
) as net_balance
from client c join
balance_movements bm
on bm.clientid = c.id
您可以像这样只加上退款总额并减去付款总额:
SELECT 500 +
(SELECT SUM(import) FROM balance_Movements WHERE movementType = 'refund')
- (SELECT SUM(import) FROM balance_Movements WHERE movementType = 'payment') AS total
结果:435.05
我认为最简单的方法是使用 SUM
和条件聚合函数 window 函数来累加 balance
SELECT c.balance +SUM(CASE WHEN movementType = 'payment' THEN - import
WHEN movementType = 'refund' THEN import
ELSE 0 END
) OVER(ORDER BY b.id) Total
FROM client c
JOIN balance_Movements b on c.id = b.clientid
但是如果你的dbms不支持window函数,你可以尝试在select
中正确使用子查询
SELECT c.balance +
(
SELECT SUM(CASE WHEN movementType = 'payment' THEN - import
WHEN movementType = 'refund' THEN import
ELSE 0 END)
FROM balance_Movements bb
WHERE bb.id <= b.id and b.clientid = bb.clientid
) Total
FROM client c
JOIN balance_Movements b on c.id = b.clientid
试一试...
IF OBJECT_ID('tempdb..#balance_Movements', 'U') IS NOT NULL
BEGIN DROP TABLE #balance_Movements; END;
CREATE TABLE #balance_Movements (
id INT NOT NULL,
clientId INT,
movementType VARCHAR (200),
import DECIMAL (9, 2) NOT NULL,
dateMovement DATETIME,
PRIMARY KEY (id)
);
INSERT INTO #balance_Movements (id, clientid, movementType, import, dateMovement) VALUES
('1', '1', 'payment', '50', '2018/05/11'),
('2', '1', 'refund', '25.05', '2018/05/10'),
('3', '1', 'refund', '60', '2018/04/06'),
('4', '1', 'payment', '100', '2018/04/03');
--=============================================================
DECLARE @_start DECIMAL(9,2) = 500;
SELECT
*,
running_total = @_start - SUM(CASE WHEN bm.movementType = 'refund' THEN -1 * bm.import ELSE bm.import END) OVER (PARTITION BY bm.clientId ORDER BY bm.dateMovement desc)
FROM
#balance_Movements bm;
结果...
id clientId movementType import dateMovement running_total
----------- ----------- ------------ ---------- ----------------------- --------------
1 1 payment 50.00 2018-05-11 00:00:00.000 450.00
2 1 refund 25.05 2018-05-10 00:00:00.000 475.05
3 1 refund 60.00 2018-04-06 00:00:00.000 535.05
4 1 payment 100.00 2018-04-03 00:00:00.000 435.05
我有这个 table 结构:
CREATE TABLE IF NOT EXISTS `client` (
`id` int(6) unsigned NOT NULL,
`name` varchar(200),
`balance` decimal NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `client` (`id`, `name`, `balance`) VALUES
('1', 'Pepito', '500');
CREATE TABLE IF NOT EXISTS `balance_Movements` (
`id` int(6) unsigned NOT NULL,
`clientId` int(6),
`movementType` varchar(200),
`import` decimal NOT NULL,
`dateMovement` datetime,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `balance_Movements` (`id`, `clientid`, `movementType`, `import`, `dateMovement`) VALUES
('1', '1', 'payment', '50', '2018/05/11'),
('2', '1', 'refund', '25.05', '2018/05/10'),
('3', '1', 'refund', '60', '2018/04/06'),
('4', '1', 'payment', '100', '2018/04/03');
客户开始时有:500€ --> 所以声明变量将是这样的:
declare @total_balance as decimal;
set @total_balance = (select balance from client where id = 1);
Result
------
500
我需要在@total_balance的结果后进行更改,取最后一行的值:
示例:
Table_balance_Movements
------------------------
Total
-----
450
475.05
535.05
435.05
解释:
450 -->客户端是500开头的,所以如果movement类型是payment我需要把client的balance减去import movement,保存数据在 @total_balance 中,稍后使用 = 500 - 50 = 450
475.05 --> 我得到了 @total_balance 的值和 25.05 的总和,因为在这一行中,移动类型是 refund = 450 + 25.05 = 475.05
535.05 --> 同样的事情,我从 @total_balance 变量中获取值并查看移动的类型并减去或求和 import = 475.05 + 60 = 535.05
435.05 --> 535.05 - 100 = 435.05
我想做类似这个概念的东西:
declare @total_balance as decimal;
set @total_balance = (select balance from client where id = 1);
select (case when movementType = 'payment' then (@total_balance = @total_balance - import)
when movementType = 'refund' then (@total_balance = @total_balance + import) end) as total
from balance_Movements;
有可能吗?谢谢
您可以使用累加和 window 函数解决此问题。以下将在 SQL 服务器和 MySQL 8+
中工作select c.*,
(c.balance +
sum(case when bm.movement_type = 'payment' then - import
when bm.movement_type = 'refund' then import
end) over (partition by c.id order by bm.datemovement)
) as net_balance
from client c join
balance_movements bm
on bm.clientid = c.id
您可以像这样只加上退款总额并减去付款总额:
SELECT 500 +
(SELECT SUM(import) FROM balance_Movements WHERE movementType = 'refund')
- (SELECT SUM(import) FROM balance_Movements WHERE movementType = 'payment') AS total
结果:435.05
我认为最简单的方法是使用 SUM
和条件聚合函数 window 函数来累加 balance
SELECT c.balance +SUM(CASE WHEN movementType = 'payment' THEN - import
WHEN movementType = 'refund' THEN import
ELSE 0 END
) OVER(ORDER BY b.id) Total
FROM client c
JOIN balance_Movements b on c.id = b.clientid
但是如果你的dbms不支持window函数,你可以尝试在select
SELECT c.balance +
(
SELECT SUM(CASE WHEN movementType = 'payment' THEN - import
WHEN movementType = 'refund' THEN import
ELSE 0 END)
FROM balance_Movements bb
WHERE bb.id <= b.id and b.clientid = bb.clientid
) Total
FROM client c
JOIN balance_Movements b on c.id = b.clientid
试一试...
IF OBJECT_ID('tempdb..#balance_Movements', 'U') IS NOT NULL
BEGIN DROP TABLE #balance_Movements; END;
CREATE TABLE #balance_Movements (
id INT NOT NULL,
clientId INT,
movementType VARCHAR (200),
import DECIMAL (9, 2) NOT NULL,
dateMovement DATETIME,
PRIMARY KEY (id)
);
INSERT INTO #balance_Movements (id, clientid, movementType, import, dateMovement) VALUES
('1', '1', 'payment', '50', '2018/05/11'),
('2', '1', 'refund', '25.05', '2018/05/10'),
('3', '1', 'refund', '60', '2018/04/06'),
('4', '1', 'payment', '100', '2018/04/03');
--=============================================================
DECLARE @_start DECIMAL(9,2) = 500;
SELECT
*,
running_total = @_start - SUM(CASE WHEN bm.movementType = 'refund' THEN -1 * bm.import ELSE bm.import END) OVER (PARTITION BY bm.clientId ORDER BY bm.dateMovement desc)
FROM
#balance_Movements bm;
结果...
id clientId movementType import dateMovement running_total
----------- ----------- ------------ ---------- ----------------------- --------------
1 1 payment 50.00 2018-05-11 00:00:00.000 450.00
2 1 refund 25.05 2018-05-10 00:00:00.000 475.05
3 1 refund 60.00 2018-04-06 00:00:00.000 535.05
4 1 payment 100.00 2018-04-03 00:00:00.000 435.05