我有一张这样的桌子
+--------+------------+-----------+
| id | volume | price |
+--------+------------+-----------+
| 1 | 1.0000 | 14250.00 |
| 2 | 0.2500 | 14251.10 |
| 3 | 0.2500 | 14250.00 |
| 4 | 0.0050 | 14200.00 |
| 5 | 0.5000 | 14255.01 |
+--------+------------+-----------+简单地说,如果数量1.7500,如何选择爱波洛通过订购(最高的价格)
+--------+------------+-----------+
| id | volume | price |
+--------+------------+-----------+
| 5 | 0.5000 | 14255.01 |
| 2 | 0.2500 | 14251.10 |
| 1 | 1.0000 | 14250.00 |
+--------+------------+-----------+如果卷为1.5000,则还选择计算到输入卷所需的最少数量的记录。
+--------+------------+-----------+
| id | volume | price |
+--------+------------+-----------+
| 5 | 0.5000 | 14255.01 |
| 1 | 1.0000 | 14250.00 |
+--------+------------+-----------+有些人说我不能用sql做这件事。
发布于 2017-10-09 03:22:30
您需要使用约简方法来慢慢计算构成目标卷的部分。比如1.75,你说的是1.00,然后是0.5,然后是0.25。您可以使用循环使用模数计算余数,然后使用该余数查找下一个小于或等于您的值的最大体积。
这就是我要做的(也许有更好的方法,但这是可行的)
CREATE TABLE VolumePrice (
id int not null,
volume decimal(9,4) not null,
price decimal(9,2) not null
);
insert VolumePrice (id, volume, price)
values (1, 1.0000, 14250.00),
(2,0.2500,14251.10),
(3,0.2500,14250.00),
(4,0.0050,14200.00),
(5,0.5000,14255.01);
-- create a temp table to hold the output
create table output (
id int auto_increment not null primary key,
remainder decimal(9,2),
volume decimal(9,2)
);
DELIMITER //
create procedure do_insert()
begin
set @v = 1.75;
set @remainder = @v;
while @remainder > 0
do
insert output(remainder, volume)
select @remainder % max(volume)
, max(volume) as volume
from volumeprice
where volume <= @remainder;
set @remainder = (select remainder
from output
order by id desc
limit 1);
end while;
end;
//
DELIMITER ;
CALL do_insert();
select v.*
from output as o
join (select volume, max(price) as max_price
from volumeprice
group by volume) as vp on vp.volume = o.volume
-- I only link back to the volumeprice table here to obtain the id,
-- if you do't need the id you can remove this part and just select vp.* instead...
join volumeprice as v
on v.volume = vp.volume
and v.price = vp.max_price;这里有一个SQL Fiddle,它似乎能做到这一点。
发布于 2017-10-10 15:13:18
看来你有两个问题。
第一项:
简单地说,如果数量1.7500,如何选择爱波洛通过订购(最高的价格)
下面是一个应该提供结果集的解决方案:
SELECT t.id, t.volume, t.price,
(SELECT SUM(volume) FROM buy WHERE (id <> t.id AND price > t.price) OR (id < t.id AND price = t.price) OR (id = t.id)) 'RequiredVolume'
FROM buy t
HAVING RequiredVolume <= '1.7500'
ORDER BY price DESC, id ASC;下面是验证输出的SQLFiddle。
至于第二个问题,这似乎是一个完全不同的问题:
如果卷为1.5000,则还选择计算到输入卷所需的最少数量的记录。
我基本上是按数量订购,而不是按价格订购,这样你就可以得到你想要的:
SELECT t.id, t.volume, t.price,
(SELECT SUM(volume) FROM buy WHERE volume > t.volume OR (id < t.id AND volume = t.volume) OR (id = t.id)) 'RequiredVolume'
FROM buy t
HAVING RequiredVolume <= '1.5000'
ORDER BY price DESC, id ASC;下面是验证输出的SQLFiddle。
发布于 2017-10-24 10:33:58
同样的问题可以在PURE SQL中写成,而不用RBAR或REcursive。
这个脚本在Sql server 2005+中,我认为它可以很容易地转换成mySQL。
让我知道限制
首先创建数字表。
SELECT TOP (1048576)
n = ISNULL(CONVERT(integer, ROW_NUMBER() OVER (ORDER BY (SELECT NULL))), 0)
INTO dbo.Numbers
FROM sys.columns AS c
CROSS JOIN sys.columns AS c2
CROSS JOIN sys.columns AS c3;
CREATE UNIQUE CLUSTERED INDEX cuq
ON dbo.Numbers (n)
WITH (MAXDOP = 1, SORT_IN_TEMPDB = ON);最后的剧本,
declare @input decimal(9,4)=1.7500
if object_id('tempdb..#VolumePrice') is not null
drop table #VolumePrice
create table #VolumePrice (
id tinyint PRIMARY KEY NONCLUSTERED,
volume decimal(9,4) not null,
price decimal(9,2) not null,
bit_value AS
CONVERT
(
integer,
POWER(2, id - 1)
)
PERSISTED UNIQUE CLUSTERED
);
insert #VolumePrice (id, volume, price)
values (1, 1.0000, 14250.00),(2,0.2500,14251.10),
(3,0.2500,14250.00),(4,0.0050,14200.00),(5,0.5000,14255.01);
DECLARE
@max integer =
POWER(2,
(
SELECT COUNT(*)
FROM #VolumePrice AS s
)
) - 1;
;
WITH CTE
AS (
SELECT n.n
,c.id
,c.volume
FROM dbo.Numbers AS N
CROSS APPLY (
SELECT s.id
,s.volume
FROM #VolumePrice AS s
WHERE n.n & s.bit_value = s.bit_value
) c
WHERE N.n BETWEEN 1
AND @max
)
,cte1
AS (
SELECT n
,sum(volume) vol
,count(n) HavingLeastcount
FROM cte
GROUP BY n
HAVING sum(volume) = @input
)
SELECT *
FROM cte c
WHERE EXISTS (
SELECT n
FROM cte1 c1
WHERE n = c.n
)https://dba.stackexchange.com/questions/187970
复制相似问题