首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >按给定的卷量选择多行

按给定的卷量选择多行
EN

Database Administration用户
提问于 2017-10-08 10:29:01
回答 3查看 438关注 0票数 0

我有一张这样的桌子

代码语言:javascript
复制
+--------+------------+-----------+
| 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,如何选择爱波洛通过订购(最高的价格)

代码语言:javascript
复制
+--------+------------+-----------+
| id     | volume     | price     |
+--------+------------+-----------+
|      5 | 0.5000     |  14255.01 |
|      2 | 0.2500     |  14251.10 |
|      1 | 1.0000     |  14250.00 |
+--------+------------+-----------+

如果卷为1.5000,则还选择计算到输入卷所需的最少数量的记录。

代码语言:javascript
复制
+--------+------------+-----------+
| id     | volume     | price     |
+--------+------------+-----------+
|      5 | 0.5000     |  14255.01 |
|      1 | 1.0000     |  14250.00 |
+--------+------------+-----------+

有些人说我不能用sql做这件事。

EN

回答 3

Database Administration用户

发布于 2017-10-09 03:22:30

您需要使用约简方法来慢慢计算构成目标卷的部分。比如1.75,你说的是1.00,然后是0.5,然后是0.25。您可以使用循环使用模数计算余数,然后使用该余数查找下一个小于或等于您的值的最大体积。

这就是我要做的(也许有更好的方法,但这是可行的)

代码语言:javascript
复制
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,它似乎能做到这一点。

票数 2
EN

Database Administration用户

发布于 2017-10-10 15:13:18

看来你有两个问题。

第一项:

简单地说,如果数量1.7500,如何选择爱波洛通过订购(最高的价格)

下面是一个应该提供结果集的解决方案:

代码语言:javascript
复制
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,则还选择计算到输入卷所需的最少数量的记录。

我基本上是按数量订购,而不是按价格订购,这样你就可以得到你想要的:

代码语言:javascript
复制
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

票数 1
EN

Database Administration用户

发布于 2017-10-24 10:33:58

同样的问题可以在PURE SQL中写成,而不用RBARREcursive

这个脚本在Sql server 2005+中,我认为它可以很容易地转换成mySQL。

让我知道限制

首先创建数字表。

代码语言:javascript
复制
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);

最后的剧本,

代码语言:javascript
复制
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
        )
票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/187970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档