Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server NTILE-不同四分位数中的相同值_Sql Server_Sql Server 2008 - Fatal编程技术网

Sql server SQL Server NTILE-不同四分位数中的相同值

Sql server SQL Server NTILE-不同四分位数中的相同值,sql-server,sql-server-2008,Sql Server,Sql Server 2008,我有一个场景,在这个场景中,我使用下面的SQL Server NTILE函数将许多结果拆分为四分之一。目标是使每个类中的行数相等 case NTILE(4) over (order by t2.TotalStd) when 1 then 'A' when 2 then 'B' when 3 then 'C' else 'D' end as Class 结果表如下所示,在4个类别组a、B、C和D之间有(9,9,8,8)分 有两个结果引起了我的一个问题,两行的总std值相同,为30,但分配

我有一个场景,在这个场景中,我使用下面的SQL Server NTILE函数将许多结果拆分为四分之一。目标是使每个类中的行数相等

case NTILE(4) over (order by t2.TotalStd) 
   when 1 then 'A' when 2 then 'B' when 3 then 'C' else 'D' end as Class
结果表如下所示,在4个类别组a、B、C和D之间有(9,9,8,8)分

有两个结果引起了我的一个问题,两行的总std值相同,为30,但分配给不同的四分位数

8   30  A
2   30  B
我想知道有没有办法确保具有相同值的行被分配到同一个四分位数?我可以通过另一列进行分组或分区来获得这种行为吗

Pos TotalStd    class
1   16  A
2   23  A
3   21  A
4   29  A
5   25  A
6   26  A
7   28  A
8   30  A
9   29  A
1   31  B
2   30  B
3   32  B
4   32  B
5   34  B
6   32  B
7   34  B
8   32  B
9   33  B
1   36  C
2   35  C
3   35  C
4   35  C
5   40  C
6   38  C
7   41  C
8   43  C
1   43  D
2   48  D
3   45  D
4   47  D
5   44  D
6   48  D
7   46  D
8   57  D
真的,我不知道你期望这里会发生什么。按照您的要求,SQL Server已将数据分成4组,大小尽可能相等。你想发生什么?看看这个例子:

declare @data table ( x int )

insert @data values 
(1),(2),
(2),(3),
(3),(4),
(4),(5)

select  
    x,
    NTILE(4) over (order by x) as ntile
from @data
结果:

x           ntile
----------- ----------
1           1
2           1
2           2
3           2
3           3
4           3
4           4
5           4
x   new_ntile
---------------
1   1
2   1
2   1
3   2
3   2
4   3
4   3
5   4
现在,每个ntile组都与旁边的组共享一个值!但是它还能做什么呢?

试试这个:

; with a as (
                select TotalStd,Class=case ntile(4)over( order by TotalStd )
                                when 1 then 'A'
                                when 2 then 'B'
                                when 3 then 'C'
                                when 4 then 'D'
                                end
                from t2
                group by TotalStd
)
select d.*, a.Class from t2 d
inner join a on a.TotalStd=d.TotalStd
order by Class,Pos;

您需要使用rank函数重新创建Ntile函数。 rank函数为具有相同值的行提供相同的排名。后面的值“跳”到下一个列,就好像使用了行号一样。 我们可以使用此行为来模拟Ntile函数,强制它为具有相同值的行提供相同的Ntile值。但是,这将导致Ntile分区的大小不同。 有关使用4个箱子的新NTIL,请参见以下示例:

declare @data table ( x int )

insert @data values 
(1),(2),
(2),(3),
(3),(4),
(4),(5)

select  
    x,
    1+(rank() over (order by x)-1) * 4 / count(1) over (partition by (select 1)) as new_ntile
from @data
结果:

x           ntile
----------- ----------
1           1
2           1
2           2
3           2
3           3
4           3
4           4
5           4
x   new_ntile
---------------
1   1
2   1
2   1
3   2
3   2
4   3
4   3
5   4

这里我们有一张34行的桌子

DECLARE @x TABLE (TotalStd INT) 
INSERT @x (TotalStd) VALUES (16), (21), (23), (25), (26), (28), (29), (29), (30), (30), (31), (32), (32), (32), (32), (33), (34), 
    (34), (35), (35), (35), (36), (38), (40), (41), (43), (43), (44), (45), (46), (47), (48), (48), (57)
SELECT '@x', TotalStd FROM @x ORDER BY TotalStd
我们想分成四分位数。如果我们使用
NTILE
,铲斗尺寸将大致相同(每排8到9行),但系材会任意断裂:

SELECT '@x with NTILE', TotalStd, NTILE(4) OVER (ORDER BY TotalStd) quantile FROM @x
查看30如何显示两次:一次在分位数1中,一次在分位数2中。类似地,43同时出现在分位数3和4中

我应该找到的是分位数1中的10项,分位数2中的8项,分位数3中的7项和分位数4中的9项(也就是说,不是一个完美的9-8-9-8分割,但如果我们不允许任意打破联系,这种分割是不可能的)。我可以使用
NTILE
来确定临时表中的截止点:

DECLARE @cutoffs TABLE (quantile INT, min_value INT, max_value INT)

INSERT @cutoffs (quantile, min_value)
SELECT y.quantile, MIN(y.TotalStd)
FROM (SELECT TotalStd, NTILE(4) OVER (ORDER BY TotalStd) AS quantile FROM @x) y
GROUP BY y.quantile

-- The max values are the minimum values of the next quintiles
UPDATE c1 SET c1.max_value = ISNULL(C2.min_value, (SELECT MAX(TotalStd) + 1 FROM @x))
FROM @cutoffs c1 LEFT OUTER JOIN @cutoffs c2 ON c2.quantile - 1 = c1.quantile

SELECT '@cutoffs', * FROM @cutoffs
我们将使用
@cutoffs
表格中的边界值创建最终表格:

SELECT x.TotalStd, c.quantile FROM @x x 
    INNER JOIN @cutoffs c ON x.TotalStd >= c.min_value AND x.TotalStd < c.max_value
从@x选择x.TotalStd,c.quantile
x.TotalStd>=c.min\u值和x.TotalStd
这就是
NTILE
的工作原理,如果您所有的基础都具有相同的
TotalStd
并想要进行四分位数,会发生什么情况?它将在4个不同的组上拆分值。您能解释一下它是如何工作的吗?而
partitionby(select 1)
应该做什么呢?“overpartitionby”子句对“partitionby”列中的每个值运行“count(1)”聚合。假设您有一个包含3个字段的聚合销售表-商店、工作日、销售金额。你想知道每个工作日每个商店的销售额份额。您可以使用此查询:“选择门店、工作日、销售金额/总额(销售金额)超过(按工作日划分)”。如果您没有工作日,那么要运行over分区,您需要指示一个分区列。既然没有,你就用这个把戏:“选择商店,销售金额/总额(销售金额)超过(按分区(选择1))我们必须在分区的两边使用相同的分区吗?我的意思是:
1+(排名()超过(按商店分区,平日按销售额排序)-1)*4/计数(1)超过(按商店分区,平日)
如果您想在这些组中运行NTIL,那么是的。我认为您的解决方案不能保证相同价值的销售不会跳转到两个不同的分块中。例如,我有一半的销售案例具有相同价值,而其他销售案例则不同。因此,我希望前一半的销售案例跳转到第一个分块中。这是n或者我做错了什么。我认为这里的问题是解决关系的第二个变量是任意的。