window.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. from django.db.models.expressions import Func
  2. from django.db.models.fields import FloatField, IntegerField
  3. __all__ = [
  4. "CumeDist",
  5. "DenseRank",
  6. "FirstValue",
  7. "Lag",
  8. "LastValue",
  9. "Lead",
  10. "NthValue",
  11. "Ntile",
  12. "PercentRank",
  13. "Rank",
  14. "RowNumber",
  15. ]
  16. class CumeDist(Func):
  17. function = "CUME_DIST"
  18. output_field = FloatField()
  19. window_compatible = True
  20. class DenseRank(Func):
  21. function = "DENSE_RANK"
  22. output_field = IntegerField()
  23. window_compatible = True
  24. class FirstValue(Func):
  25. arity = 1
  26. function = "FIRST_VALUE"
  27. window_compatible = True
  28. class LagLeadFunction(Func):
  29. window_compatible = True
  30. def __init__(self, expression, offset=1, default=None, **extra):
  31. if expression is None:
  32. raise ValueError(
  33. "%s requires a non-null source expression." % self.__class__.__name__
  34. )
  35. if offset is None or offset <= 0:
  36. raise ValueError(
  37. "%s requires a positive integer for the offset."
  38. % self.__class__.__name__
  39. )
  40. args = (expression, offset)
  41. if default is not None:
  42. args += (default,)
  43. super().__init__(*args, **extra)
  44. def _resolve_output_field(self):
  45. sources = self.get_source_expressions()
  46. return sources[0].output_field
  47. class Lag(LagLeadFunction):
  48. function = "LAG"
  49. class LastValue(Func):
  50. arity = 1
  51. function = "LAST_VALUE"
  52. window_compatible = True
  53. class Lead(LagLeadFunction):
  54. function = "LEAD"
  55. class NthValue(Func):
  56. function = "NTH_VALUE"
  57. window_compatible = True
  58. def __init__(self, expression, nth=1, **extra):
  59. if expression is None:
  60. raise ValueError(
  61. "%s requires a non-null source expression." % self.__class__.__name__
  62. )
  63. if nth is None or nth <= 0:
  64. raise ValueError(
  65. "%s requires a positive integer as for nth." % self.__class__.__name__
  66. )
  67. super().__init__(expression, nth, **extra)
  68. def _resolve_output_field(self):
  69. sources = self.get_source_expressions()
  70. return sources[0].output_field
  71. class Ntile(Func):
  72. function = "NTILE"
  73. output_field = IntegerField()
  74. window_compatible = True
  75. def __init__(self, num_buckets=1, **extra):
  76. if num_buckets <= 0:
  77. raise ValueError("num_buckets must be greater than 0.")
  78. super().__init__(num_buckets, **extra)
  79. class PercentRank(Func):
  80. function = "PERCENT_RANK"
  81. output_field = FloatField()
  82. window_compatible = True
  83. class Rank(Func):
  84. function = "RANK"
  85. output_field = IntegerField()
  86. window_compatible = True
  87. class RowNumber(Func):
  88. function = "ROW_NUMBER"
  89. output_field = IntegerField()
  90. window_compatible = True