SQL查询根据3条标准将所有记录划分为70:30比率

时间:2016-09-03 12:55:29

标签: sql sql-server tsql

我有一张表格如下:

CREATE TABLE [My_Table](
    [Id] int,
    [Amount] [money] NOT NULL,
    [Rate] [decimal](3, 2) NOT NULL,
    [Status] [varchar](50) NOT NULL,
    [Trend] [varchar](50) NOT NULL
)

Status列有3个潜在值:A,B或C

Amount列有8个潜在值:$ 1.00到$ 8.00

Rate列有21个潜在值:0.06到0.26

我试图找出一个允许我将所有行分开的查询,这样我就能得到每个排列的70/30分割。

Trend列将用于ORDER BY,以便我可以有效地在一个查询中获得前70%,在另一个查询中获得最低30%,这样我就可以获得70/30分割对于每个可能值的排列。如此有效地运行:

第一次排列 - 使用相同的WHERE值运行两次(70%& 30%):

SELECT TOP (70) PERCENT [Id] FROM My_Table WHERE (Rate = 0.06) AND (Status = 'A') AND (Amount = 1.00) ORDER BY [Trend] DESC
SELECT TOP (30) PERCENT [Id] FROM My_Table WHERE (Rate = 0.06) AND (Status = 'A') AND (Amount = 1.00) ORDER BY [Trend] ASC

第二次排列(将费率增加.01)所有其他因素相同

SELECT TOP (70) PERCENT [Id] FROM My_Table WHERE (Rate = 0.07) AND (Status = 'A') AND (Amount = 1.00) ORDER BY [Trend] DESC
SELECT TOP (30) PERCENT [Id] FROM My_Table WHERE (Rate = 0.07) AND (Status = 'A') AND (Amount = 1.00) ORDER BY [Trend] ASC

等...

直到探索了所有可能的费率值。然后使用下一个状态值重新执行该操作=' B'然后重新开始使用第一个Rate值0.06:

SELECT TOP (70) PERCENT [Id] FROM My_Table WHERE (Rate = 0.06) AND (Status = 'B') AND (Amount = 1.00) ORDER BY [Trend] DESC
SELECT TOP (30) PERCENT [Id] FROM My_Table WHERE (Rate = 0.06) AND (Status = 'B') AND (Amount = 1.00) ORDER BY [Trend] ASC

...依此类推,直到3个过滤列中的所有32个可能值都已用尽并且已经选择了所有可能的排列。

值得指出的是,并非所有排列都会产生结果,因为有更多可能的标准而不是表中的行(~6000)。

最终,我想根据分割将结果转换为两个新表,但是一旦我有办法遍历所有排列,那部分应该是微不足道的。起初我想的是一些3级光标,但我想可能有一个比我更聪明的人能想到的更好的方法!

2 个答案:

答案 0 :(得分:0)

您可以通过枚举每个排列中的值,然后根据枚举获取样本来实现此目的。

例如,要获得每个金额/费率/状态组中70%的最高趋势值:

select t.*
from (select t.*,
             row_number() over (partition by amount, rate, status order by trend desc) as seqnum,
             count(*) over (partition by amount, rate, status) as cnt
      from my_table t
     ) t
where seqnum <= cnt * 0.7;

作为注释:这是所谓的分层样本的一个例子。

此外,在tie的情况下,具有相同trend值的行可以同时进入较低和较高的组。如果这是一个问题,请使用rank()而不是row_number()

答案 1 :(得分:0)

我认为,NTILE功能可以帮助您:

if askUser("Is it unresponsive"):

它将结果集分配到10个“磁贴”上,并按SELECT [Id], NTILE(10) OVER(ORDER BY Id) AS Rate FROM My_Table WHERE (Rate = 0.06) AND (Status = 'B') AND (Amount = 1.00) 列(&lt; = 7或&gt; 7)过滤以分隔值