我試圖找出SQL Server 2008中函數的第95百分位和中位數構建,但我不知道MS爲什麼不給他們提供支持,真的很煩人......我們的工作地點報告非常複雜,想要一個直接的功能,或者可能是一個DLL文件,我可以與SQL服務器組裝,以使用它作爲正常功能。SQL Server 2008中的中位數和第95百分位數? - NHS報告要求
可以任何一個建議。提前致謝。
Reagrds 阿里
我試圖找出SQL Server 2008中函數的第95百分位和中位數構建,但我不知道MS爲什麼不給他們提供支持,真的很煩人......我們的工作地點報告非常複雜,想要一個直接的功能,或者可能是一個DLL文件,我可以與SQL服務器組裝,以使用它作爲正常功能。SQL Server 2008中的中位數和第95百分位數? - NHS報告要求
可以任何一個建議。提前致謝。
Reagrds 阿里
我對NHS的工作以及在這裏是whcih我寫找出正中,MAX的SQL,和第95百分位數 檢查了這一點,並給我發電子郵件[email protected]
WITH kali1 (k1, k2, k3, k4, k5, k6, k7)
AS (SELECT MinsInAE ,
HoursInAE ,
DaysInAE AS DaysInAE ,
Month_Name ,
YearName ,
InternalNo ,
ROW_NUMBER() OVER (PARTITION BY Month_Name ORDER BY MinsInAE ASC) AS 'Row Number'
FROM AE.FactAandE
INNER JOIN AE.PMI ON AE.FactAandE.FK_PaitentMasterIndex = AE.PMI.PK_Patient
INNER JOIN dbo.TimeDimension ON dbo.TimeDimension.DateId = AE.FactAandE.FK_date
WHERE YearName = 'Calendar 2010'
),
kali2 (k21, k22, k23)
AS (SELECT MAX(k7) * 95/100 ,
k4 ,
MAX(k7)
FROM kali1
GROUP BY k4
),
kali3 (k31, k32)
AS (SELECT AVG(1.0E * MinsInAE) AS Median ,
Month_Name
FROM (SELECT MinsInAE ,
Month_Name ,
2
* ROW_NUMBER() OVER (PARTITION BY Month_Name ORDER BY MinsInAE)
- COUNT(*) OVER (PARTITION BY Month_Name) AS y
FROM AE.FactAandE
INNER JOIN AE.PMI ON AE.FactAandE.FK_PaitentMasterIndex = AE.PMI.PK_Patient
INNER JOIN dbo.TimeDimension ON dbo.TimeDimension.DateId = AE.FactAandE.FK_date
WHERE YearName = 'Calendar 2010'
) AS d
WHERE y BETWEEN 0 AND 2
GROUP BY Month_Name
),
kali4 (k41, k42, k43, k44, k46, k47)
AS (SELECT MinsInAE ,
HoursInAE ,
DaysInAE AS DaysInAE ,
Month_Name ,
YearName ,
InternalNo
FROM AE.FactAandE
INNER JOIN AE.PMI ON AE.FactAandE.FK_PaitentMasterIndex = AE.PMI.PK_Patient
INNER JOIN dbo.TimeDimension ON dbo.TimeDimension.DateId = AE.FactAandE.FK_date
WHERE YearName = 'Calendar 2010'
),
kali5 (k51, k52, k53)
AS (SELECT kali2.k22 AS Month_Name ,
(kali1.k1) AS percentilevalue ,
kali2.k21 AS percentilerow
FROM kali2
INNER JOIN kali1 ON kali1.k4 = kali2.k22
WHERE kali1.k7 = kali2.k21
)
SELECT kali3.k31 AS Median ,
kali3.k32 AS Month_Name ,
MAX(kali4.k41) AS Max_Mins_In_AE ,
SUM(kali4.k41) AS Mins_IN_AE ,
kali5.k51 AS Month_Name ,
kali5.k52 AS percentile
FROM kali3
LEFT JOIN kali4 ON kali3.k32 = kali4.k44
LEFT JOIN kali5 ON kali5.k51 = kali3.k32
GROUP BY kali3.k31 ,
kali3.k32 ,
kali5.k51 ,
kali5.k52
95日百分公式是 MAX(ROWNUMBER)*100分之95
WITH kali1(k1, k2, k3, k4, k5, k6, k7) AS
(
SELECT MinsInAE,
HoursInAE,
DaysInAE AS DaysInAE,
Month_Name,
YearName,
InternalNo,
ROW_NUMBER() OVER(PARTITION BY Month_Name ORDER BY MinsInAE ASC) AS
'Row Number'
FROM AE.FactAandE
INNER JOIN AE.PMI
ON AE.FactAandE.FK_PaitentMasterIndex = AE.PMI.PK_Patient
INNER JOIN dbo.TimeDimension
ON dbo.TimeDimension.DateId = AE.FactAandE.FK_date
WHERE YearName = 'Calendar 2010'
)
,
kali2(k21, k22, k23)
AS
(
SELECT MAX(k7) * 95/100,
k4,
MAX(k7)
FROM kali1
GROUP BY
k4
)
SELECT kali2.k21 AS percentilerow,
kali2.k22 AS Month_Name,
(kali1.k1) AS percentilevalue
FROM kali2
INNER JOIN kali1
ON kali1.k4 = kali2.k22
WHERE kali1.k7 = kali2.k21
請格式化此sql代碼。 –
您可以創建在Visual Studio中的DLL通過創建SQL Server中使用自定義的聚合函數來做到這一點。爲此,創建一個新的Visual Studio項目,並將目標框架設置爲.NET 3.5(這適用於SQL 2008,它在SQL 2012中可能不同)。然後創建一個類文件並放入以下代碼或c#等價物。
請注意,此算法會獲得與指定百分位數最接近的值。如果你想使用不同的百分比算法,那麼可以修改代碼。
此過程允許用戶輸入任何百分點來查詢。查詢應該是這樣的:SELECT dbo.Percentile(價值95)FROM表
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlTypes
Imports System.IO
<Serializable>
<SqlUserDefinedAggregate(Format.UserDefined, IsInvariantToNulls:=True, IsInvariantToDuplicates:=False, _
IsInvariantToOrder:=True, MaxByteSize:=-1, IsNullIfEmpty:=True)>
Public Class Percentile
Implements IBinarySerialize
Private _items As List(Of Decimal)
Private _percentile As Integer
Public Sub Init()
_items = New List(Of Decimal)()
End Sub
Public Sub Accumulate(value As SqlDecimal, percentile As SqlInt32)
_percentile = percentile
If Not value.IsNull Then
_items.Add(value.Value)
End If
End Sub
Public Sub Merge(other As Percentile)
_percentile = other._percentile
If other._items IsNot Nothing Then
_items.AddRange(other._items)
End If
End Sub
Public Function Terminate() As SqlDecimal
If _items.Count <> 0 Then
Dim result As Decimal
_items = _items.OrderBy(Function(i) i).ToList()
Dim index = Convert.ToInt32(Math.Round((_percentile/100D) * _items.Count, 0))
If (index <> 0) Then
index -= 1
End If
result = _items(index)
Return New SqlDecimal(result)
Else
Return New SqlDecimal()
End If
End Function
Public Sub Read(r As BinaryReader) Implements IBinarySerialize.Read
'deserialize it from a string
Dim list = r.ReadString()
If Not (String.IsNullOrEmpty(list)) Then
Dim index = list.IndexOf("|"c)
If index <> -1 Then
_items = New List(Of Decimal)
_percentile = Convert.ToInt32(list.Substring(0, index))
list = list.Substring(index + 1)
For Each value In list.Split(","c)
Dim number As Decimal
If Decimal.TryParse(value, number) Then
_items.Add(number)
End If
Next
End If
End If
End Sub
Public Sub Write(w As BinaryWriter) Implements IBinarySerialize.Write
'serialize the list to a string
Dim list As String = ""
If (_items IsNot Nothing AndAlso _items.Count > 0) Then
list = Convert.ToString(_percentile) + "|"
For Each item In _items
If Not list.EndsWith("|") Then
list += ","
End If
list += item.ToString("#0.0##")
Next
End If
w.Write(list)
End Sub
End Class
然後編譯它,DLL和PDB文件複製到您的SQL Server計算機和SQL Server運行下面的命令:
CREATE ASSEMBLY CustomAggregate FROM '{path to your DLL}'
WITH PERMISSION_SET=SAFE;
GO
CREATE AGGREGATE Percentile(@value decimal(9, 3), @percentile int)
RETURNS decimal(9, 3)
EXTERNAL NAME [CustomAggregate].[{namespace of your DLL}.Percentile];
GO
Cheers Mladen Prajdic!我將研究這個函數和文章,但如果有人能夠幫助找到一個動態鏈接libraby(dll)將其與SQL服務器組裝起來,使這些功能成爲內置將非常有幫助。再次感謝您的回覆 –