如何从现有排名值创建具有递增排名值的运行范围的表?

Posted

技术标签:

【中文标题】如何从现有排名值创建具有递增排名值的运行范围的表?【英文标题】:How can I create a table with a running range of incremented rank values from existing rank values? 【发布时间】:2017-03-03 04:40:26 【问题描述】:

我在 Access 2013 中有一个表,其中包含以下字段:唯一位置代码(短文本类型);每个分数都有唯一值的分数(短文本类型);以及每个 Code 的唯一值,按 Score 降序排列,称为 Rank(数字,Long Integer 类型)。大约有 8,000 条记录。

我想创建一个表格,其中每个 Rank 值在每个 Rank 值的四分位数 (25%) 内的运行范围 - 即,将 1 到 994 添加到每个 Rank 值(994 是总 Rank 值的 12.5%)所有 Rank 值都大于 ,并且对于所有小于每个 Code 的 Rank 值的 Rank 值从每个 Rank 值中减去 1 到 994,以创建总共 1,987 个具有相同 Code 值的 Rank 值记录。

我将使用查询中的排名值将每个代码和排名连接到该排名的四分位数/队列中的所有其他记录。我可以创建查询 - 我知道这将有一个巨大的结果集 - 我只需要首先为每个代码和排名创建运行四分位数/队列排名值的表。

非常感谢任何帮助。当然,我完全赞成在 mysql 中尝试这样做。显然,如果有更简单的方法来实现相同的结果,那也是值得赞赏的。

【问题讨论】:

【参考方案1】:

好吧,继续吧。首先,这里有一个函数,可以使用您希望的任何方法为您计算四分位数:

Public Function GetQuartile( _
  ByVal strTable As String, _
  ByVal strField As String, _
  ByVal bytQuartile As Byte, _
  Optional ByVal bytMethod As Byte, _
  Optional ByVal strFilter As String) _
  As Double

  ' strTable :    Name of the table/query to analyze.
  ' strField :    Name of the field to analyze.
  ' bytQuartile:  Which min/max or median/quartile to calculate.
  ' bytMethod:    Method for calculation of lower/higher quartile.
  ' strFilter:    Optional filter expression.
  '
  ' Returns:
  '   Minimum, maximum, median or upper/lower quartile
  '   of strField of strTable filtered on strFilter.
  '
  ' 2006-03-05. Cactus Data ApS, CPH.


' Reference for methods for calculation as explained here:
'   http://www.daheiser.info/excel/notes/noteh.pdf
' Note: Table H-4, p. 4, has correct data for dataset 1-96 while
'   datasets 1-100 to 1-97 actually are datasets 1-99 to 1-96
'   shifted one column left.
'   Thus, the dataset 1-100 is missing.
'
'   Method 3b is not implemented as no one seems to use it.
'   Neither are no example data given.
'
' Further notes on methods here:
'   http://mathforum.org/library/drmath/view/60969.html
'   http://www.haiweb.org/medicineprices/manual/quartiles_iTSS.pdf
'
' Data must be in ascending order by strField.


' L: Q1, Lower quartile.
' H: Q3, Higher quartile.
' M: Q2, Median.
' n: Count of elements.
' p: Calculated position of quartile.
' j: Element of dataset.
' g: Decimal part of p
'    to be used for interpolation between j and j+1.

' Basic operation.
' Constant values mimic those of Excel's Quartile() function.

' Find median.
Const cbytQuartMedian             As Byte = 2
' Find lower (first) quartile.
Const cbytQuartLow                As Byte = 1
' Find upper (third) quartile.
Const cbytQuartHigh               As Byte = 3
' Find minimum value.
Const cbytQuartMinimum            As Byte = 0
' Find maximum value.
Const cbytQuartMaximum            As Byte = 4

' Define default operation.
Const cbytQuartDefault = cbytQuartMedian

' Quartile calculation methods.

' Step. Mendenhall and Sincich method.
' SAS #3.
' Round up to actual element of dataset.
' L: -Int(-n/4)
' H: n-Int(-n/4)
Const cbytMethodMendenhallSincich As Byte = 1

' Average step.
' SAS #5, Minitab (%DESCRIBE), GLIM (percentile).
' Add bias of one or two on basis of n/4.
' L: (Int((n+1)/4)+Int(n/4))/2+1
' H: n-(Int((n+1)/4)+Int(n/4))/2+1
Const cbytMethodAverage           As Byte = 2

' Nearest integer to np.
' SAS #2.
' Round to nearest integer on basis of n/4.
' L: Int((n+2)/4)
' H: n-Int((n+2)/4)
' Note:
'   Reference contains an error in example data.
'   Dataset 1-100 to 1-97 (is really 1-99 to 1-96!) should read:
'   25  25  24  24
Const cbytMethodNearestInteger    As Byte = 3

' Parzen method.
' Method 1 with interpolation.
' SAS #1.
' L: n/4
' H: 3n/4
Const cbytMethodParzen            As Byte = 4

' Hazen method.
' Values midway between method 1 steps.
' GLIM (interpolate).
' Add bias of 2, don't round to actual element of dataset.
' L: (n+2)/4
' H: 3(n+2)/4
Const cbytMethodHazen             As Byte = 5

' Weibull method.
' SAS #4. Minitab (DECRIBE), SPSS, BMDP.
' Add bias of 1, don't round to actual element of dataset.
' L: (n+1)/4
' H: 3(n+1)/4
Const cbytMethodWeibull           As Byte = 6

' Freund, J. and Perles, B., Gumbell method.
' S-PLUS, R, Excel, Star Office Calc.
' Add bias of 3, don't round to actual element of dataset.
' L: (n+3)/4
' H: (3n+1)/4
Const cbytMethodFreundPerles      As Byte = 7

' Median Position.
' Median unbiased.
' L: (3n+5)/12
' H: (9n+7)/12
Const cbytMethodMedianPosition    As Byte = 8

' Bernard and Bos-Levenbach.
' L: (n/4)+0.4
' H: (3n/4)/+0.6
' Note:
'   Reference claims L to be (n/4)+0.31.
Const cbytMethodBernardLevenbach  As Byte = 9

' Blom's Plotting Position.
' Better approximation when the distribution is normal.
' L: (4n+7)/16
' H: (12n+9)/16
Const cbytMethodBlom              As Byte = 10

' Moore's first method.
' Add bias of one half step.
' L: (n+0.5)/4
' H: n-(n+0.5)/4
Const cbytMethodMoore1            As Byte = 11

' Moore's second method.
' Add bias of one or two steps on basis of (n+1)/4.
' L: (Int((n+1)/4)+Int(n/4))/2+1
' H: n-(Int((n+1)/4)+Int(n/4))/2+1
Const cbytMethodMoore2            As Byte = 12

' John Tukey's method.
' Include median from odd dataset in dataset for quartile.
' L: (1-Int(-n/2))/2
' H: n-(1-Int(-n/2))/2
Const cbytMethodTukey             As Byte = 13

' Moore and McCabe (M & M), variation of John Tukey's method.
' TI-83.
' Exclude median from odd dataset in dataset for quartile.
' L: (Int(n/2)+1)/2
' H: n-(Int(n/2)+1)/2
Const cbytMethodTukeyMM           As Byte = 14

' Additional variations between Weibull's and Hazen's methods, from
'   (i-0.000)/(n+1.00)
' to
'   (i-0.500)/(n+0.00)
'
' Variation of Weibull.
' L: n(n/4-0)/(n+1)
' H: n(3n/4-0)/(n+1)
Const cbytMethodModWeibull        As Byte = 15
' Variation of Blom.
' L: n(n/4-3/8)/(n+1/4)
' H: n(3n/4-3/8)/(n+1/4)
Const cbytMethodModBlom           As Byte = 16
' Variation of Tukey.
' L: n(n/4-1/3)/(n+1/3)
' H: n(3n/4-1/3)/(n+1/3)
Const cbytMethodModTukey          As Byte = 17
' Variation of Cunnane.
' L: n(n/4-2/5)/(n+1/5)
' H: n(3n/4-2/5)/(n+1/5)
Const cbytMethodModCunnane        As Byte = 18
' Variation of Gringorten.
' L: n(n/4-0.44)/(n+0.12)
' H: n(3n/4-0.44)/(n+0.12)
Const cbytMethodModGringorten     As Byte = 19
' Variation of Hazen.
' L: n(n/4-1/2)/n
' H: n(3n/4-1/2)/n
Const cbytMethodModHazen          As Byte = 20


' Define default method to calculate quartiles.
Const cbytMethodDefault = cbytMethodFreundPerles

Static dbs      As DAO.Database
Static rst      As DAO.Recordset

Dim strSQL      As String
Dim lngNumber   As Long
Dim dblPosition As Double
Dim lngPosition As Long
Dim dblInterpol As Double
Dim dblValueOne As Double
Dim dblValueTwo As Double
Dim dblQuartile As Double

' Use default calculation if choice of calculation is outside range.
If bytQuartile > 4 Then
  bytQuartile = cbytQuartDefault
End If
' Use default method if choice of method is outside range.
If bytMethod = 0 Or bytMethod > 20 Then
  bytMethod = cbytMethodDefault
End If

If dbs Is Nothing Then
  Set dbs = CurrentDb()
End If

If Len(strTable) > 0 And Len(strField) > 0 Then
  strSQL = "SELECT [" & strField & "] FROM [" & strTable & "] "
  strSQL = strSQL & "WHERE ([" & strField & "] Is Not Null) "
  If Len(strFilter) > 0 Then
    strSQL = strSQL & "AND (" & strFilter & ") "
  End If
  strSQL = strSQL & "ORDER BY [" & strField & "];"

  Set rst = dbs.OpenRecordset(strSQL)

  With rst
    If Not .EOF = True Then
      If bytQuartile = cbytQuartMinimum Then
        ' No need to count records.
        lngNumber = 1
      Else
        ' Count records.
        .MoveLast
        lngNumber = .RecordCount
      End If
      Select Case bytQuartile
        Case cbytQuartMinimum
          ' Current record is first record.
          ' Read value of this record.
        Case cbytQuartMaximum
          ' Current record is last record.
          ' Read value of this record.
        Case cbytQuartMedian
          ' Locate position of median.
          dblPosition = (lngNumber + 1) / 2
        Case cbytQuartLow
          Select Case bytMethod
            Case cbytMethodMendenhallSincich
              dblPosition = -Int(-lngNumber / 4)
            Case cbytMethodAverage
              dblPosition = (Int((lngNumber + 1) / 4) + Int(lngNumber / 4)) / 2 + 1
            Case cbytMethodNearestInteger
              dblPosition = Int((lngNumber + 2) / 4)
            Case cbytMethodParzen
              dblPosition = lngNumber / 4
            Case cbytMethodHazen
              dblPosition = (lngNumber + 2) / 4
            Case cbytMethodWeibull
              dblPosition = (lngNumber + 1) / 4
            Case cbytMethodFreundPerles
              dblPosition = (lngNumber + 3) / 4
            Case cbytMethodMedianPosition
              dblPosition = (3 * lngNumber + 5) / 12
            Case cbytMethodBernardLevenbach
              dblPosition = (lngNumber / 4) + 0.4
            Case cbytMethodBlom
              dblPosition = (4 * lngNumber + 7) / 16
            Case cbytMethodMoore1
              dblPosition = (lngNumber + 0.5) / 4
            Case cbytMethodMoore2
              dblPosition = (Int((lngNumber + 1) / 4) + Int(lngNumber / 4)) / 2 + 1
            Case cbytMethodTukey
              dblPosition = (1 - Int(-lngNumber / 2)) / 2
            Case cbytMethodTukeyMM
              dblPosition = (Int(lngNumber / 2) + 1) / 2
            Case cbytMethodModWeibull
              dblPosition = lngNumber * (lngNumber / 4) / (lngNumber + 1)
            Case cbytMethodModBlom
              dblPosition = lngNumber * (lngNumber / 4 - 3 / 8) / (lngNumber + 1 / 4)
            Case cbytMethodModTukey
              dblPosition = lngNumber * (lngNumber / 4 - 1 / 3) / (lngNumber + 1 / 3)
            Case cbytMethodModCunnane
              dblPosition = lngNumber * (lngNumber / 4 - 2 / 5) / (lngNumber + 1 / 5)
            Case cbytMethodModGringorten
              dblPosition = lngNumber * (lngNumber / 4 - 0.44) / (lngNumber + 0.12)
            Case cbytMethodModHazen
              dblPosition = lngNumber * (lngNumber / 4 - 1 / 2) / lngNumber
          End Select
        Case cbytQuartHigh
          Select Case bytMethod
            Case cbytMethodMendenhallSincich
              dblPosition = lngNumber - (-Int(-lngNumber / 4))
            Case cbytMethodAverage
              dblPosition = lngNumber - (Int((lngNumber + 1) / 4) + Int(lngNumber / 4)) / 2 + 1
            Case cbytMethodNearestInteger
              dblPosition = lngNumber - Int((lngNumber + 2) / 4)
            Case cbytMethodParzen
              dblPosition = 3 * lngNumber / 4
            Case cbytMethodHazen
              dblPosition = 3 * (lngNumber + 2) / 4
            Case cbytMethodWeibull
              dblPosition = 3 * (lngNumber + 1) / 4
            Case cbytMethodFreundPerles
              dblPosition = (3 * lngNumber + 1) / 4
            Case cbytMethodMedianPosition
              dblPosition = (9 * lngNumber + 7) / 12
            Case cbytMethodBernardLevenbach
              dblPosition = (3 * lngNumber / 4) + 0.6
            Case cbytMethodBlom
              dblPosition = (12 * lngNumber + 9) / 16
            Case cbytMethodMoore1
              dblPosition = lngNumber - (lngNumber + 0.5) / 4
            Case cbytMethodMoore2
              dblPosition = lngNumber - (Int((lngNumber + 1) / 4) + Int(lngNumber / 4)) / 2 + 1
            Case cbytMethodTukey
              dblPosition = lngNumber - (1 - Int(-lngNumber / 2)) / 2
            Case cbytMethodTukeyMM
              dblPosition = lngNumber - (Int(lngNumber / 2) + 1) / 2
            Case cbytMethodModWeibull
              dblPosition = lngNumber * (3 * lngNumber / 4) / (lngNumber + 1)
            Case cbytMethodModBlom
              dblPosition = lngNumber * (3 * lngNumber / 4 - 3 / 8) / (lngNumber + 1 / 4)
            Case cbytMethodModTukey
              dblPosition = lngNumber * (3 * lngNumber / 4 - 1 / 3) / (lngNumber + 1 / 3)
            Case cbytMethodModCunnane
              dblPosition = lngNumber * (3 * lngNumber / 4 - 2 / 5) / (lngNumber + 1 / 5)
            Case cbytMethodModGringorten
              dblPosition = lngNumber * (3 * lngNumber / 4 - 0.44) / (lngNumber + 0.12)
            Case cbytMethodModHazen
              dblPosition = lngNumber * (3 * lngNumber / 4 - 1 / 2) / lngNumber
          End Select
      End Select
      Select Case bytQuartile
        Case cbytQuartMinimum, cbytQuartMaximum
          ' Read current row.
        Case Else
          .MoveFirst
          ' Find position of first observation to retrieve.
          ' If lngPosition is 0, then upper position is first record.
          ' If lngPosition is not 0 and position is not an integer, then
          ' read the next observation too.
          lngPosition = Fix(dblPosition)
          dblInterpol = dblPosition - lngPosition
          If lngNumber = 1 Then
            ' Nowhere else to move.
            If dblInterpol < 0 Then
              ' Prevent values to be created by extrapolation beyond zero from observation one
              ' for these methods:
              '   cbytMethodModBlom
              '   cbytMethodModTukey
              '   cbytMethodModCunnane
              '   cbytMethodModGringorten
              '   cbytMethodModHazen
              '
              ' Comment this line out, if reading by extrapolation *is* requested.
              dblInterpol = 0
            End If
          ElseIf lngPosition > 1 Then
            ' Move to record to read.
            .Move lngPosition - 1
          End If
      End Select
      ' Retrieve value from first observation.
      dblValueOne = .Fields(0).Value

      Select Case bytQuartile
        Case cbytQuartMinimum, cbytQuartMaximum
          dblQuartile = dblValueOne
        Case Else
          If dblInterpol = 0 Then
            ' Only one observation to read.
            If lngPosition = 0 Then
              ' Return 0.
            Else
              dblQuartile = dblValueOne
            End If
          Else
            If lngPosition = 0 Then
              ' No first observation to retrieve.
              dblValueTwo = dblValueOne
              If dblValueOne > 0 Then
                ' Use 0 as other observation.
                dblValueOne = 0
              Else
                dblValueOne = 2 * dblValueOne
              End If
            Else
              ' Move to next observation.
              .MoveNext
              ' Retrieve value from second observation.
              dblValueTwo = .Fields(0).Value
            End If
            ' For positive values interpolate between 0 and dblValueOne.
            ' For negative values interpolate between 2 * dblValueOne and dblValueOne.
            ' Calculate quartile using linear interpolation.
            dblQuartile = dblValueOne + dblInterpol * CDec(dblValueTwo - dblValueOne)
          End If
      End Select
    End If
    .Close
  End With
Else
  ' Reset.
  Set rst = Nothing
  Set dbs = Nothing
End If

''Set rst = Nothing

  GetQuartile = dblQuartile

End Function

【讨论】:

谢谢@Gustav。这非常方便。但我不确定它是否符合我的要求。我正在努力充分描述我真正想要的东西。我认为它可以描述为每个单独等级的“增量队列” - 每个有序等级的“运行四分位数”,由每个等级正负 12.5% 范围内的所有等级值组成。 我也不知道。从一张纸开始,画出所需步骤的草图。和/或有一些示例数据,您可以在其中找出结果应该是什么。

以上是关于如何从现有排名值创建具有递增排名值的运行范围的表?的主要内容,如果未能解决你的问题,请参考以下文章

如何将具有排名值的列转换为oracle中的行

如何将具有自动递增值的列添加到 mySql 数据库的表中?

如何从包含一系列值的列创建新的递增值列?

选择 SQL Server 中排名第二的行

如何从 MySQL 中具有累积值的列创建具有增量值的列?

SQL-Rank-Example