solar_same_period_demands.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. """去年同期阳历策略 ODPS 查询。"""
  2. from app.odps.client import get_odps_client
  3. from app.strategies.odps._date_utils import resolve_solar_same_period_window, today_shanghai_date, partition_yyyymmdd
  4. from app.strategies.odps._utils import normalize_scalar, parse_video_list
  5. def build_solar_same_period_sql(
  6. *,
  7. bizdate: str,
  8. start_date: str,
  9. end_date: str,
  10. view_pv_count: int,
  11. min_contribution_score: float,
  12. rov_avg: float,
  13. ) -> str:
  14. return f"""
  15. WITH cleaned_video_metrics AS (
  16. SELECT
  17. CAST(视频id AS STRING) AS vid,
  18. rov_t0
  19. FROM loghubods.video_dimension_detail_add_column
  20. WHERE dt >= '{start_date}'
  21. AND dt <= '{end_date}'
  22. AND COALESCE(`当日分发曝光pv`, 0) >= {int(view_pv_count)}
  23. ),
  24. video_avg_metrics AS (
  25. SELECT
  26. vid,
  27. AVG(CASE WHEN rov_t0 = 0 THEN NULL ELSE rov_t0 END) AS vid_avg_rov
  28. FROM cleaned_video_metrics
  29. GROUP BY vid
  30. ),
  31. tag_vid_dedup AS (
  32. SELECT DISTINCT
  33. CAST(vid AS STRING) AS vid,
  34. 原始元素,
  35. 原始元素描述,
  36. 点类型,
  37. 元素维度,
  38. 短语,
  39. 选题,
  40. `extend`
  41. FROM loghubods.dwd_topic_decode_result_detail_di
  42. WHERE dt = MAX_PT('loghubods.dwd_topic_decode_result_detail_di')
  43. AND TRIM(原始元素) <> ''
  44. AND 原始元素 IS NOT NULL
  45. AND 元素维度 = '实质'
  46. AND 贡献分 >= {float(min_contribution_score)}
  47. )
  48. SELECT
  49. '去年同期阳历' AS strategy,
  50. md5(CONCAT('去年同期阳历', t1.原始元素, '{bizdate}')) AS demand_id,
  51. t1.原始元素 AS demand_name,
  52. COALESCE(ROUND(AVG(t2.vid_avg_rov), 6), 0) AS weight,
  53. '特征点' AS type,
  54. COUNT(DISTINCT t1.vid) AS video_count,
  55. COLLECT_SET(t1.vid) AS video_list,
  56. '{{}}' AS extend
  57. FROM tag_vid_dedup t1
  58. LEFT JOIN video_avg_metrics t2
  59. ON t1.vid = t2.vid
  60. GROUP BY t1.原始元素
  61. HAVING COALESCE(ROUND(AVG(t2.vid_avg_rov), 6), 0) >= {float(rov_avg)}
  62. ORDER BY weight DESC
  63. """
  64. def query_solar_same_period_demands(
  65. *,
  66. bizdate: str | None = None,
  67. period_days: int = 7,
  68. view_pv_count: int,
  69. min_contribution_score: float,
  70. rov_avg: float,
  71. ) -> list[dict[str, object]]:
  72. if bizdate is None:
  73. bizdate = partition_yyyymmdd(today_shanghai_date())
  74. bizdate_value, start_date, end_date = resolve_solar_same_period_window(
  75. bizdate=bizdate,
  76. period_days=period_days,
  77. )
  78. sql = build_solar_same_period_sql(
  79. bizdate=bizdate_value,
  80. start_date=start_date,
  81. end_date=end_date,
  82. view_pv_count=view_pv_count,
  83. min_contribution_score=min_contribution_score,
  84. rov_avg=rov_avg,
  85. )
  86. odps_client = get_odps_client()
  87. instance = odps_client.execute_sql(
  88. sql,
  89. hints={
  90. "odps.sql.submit.mode": "script",
  91. "odps.sql.decimal.odps2": "true",
  92. },
  93. )
  94. rows: list[dict[str, object]] = []
  95. with instance.open_reader(tunnel=True) as reader:
  96. for record in reader:
  97. rows.append(
  98. {
  99. "strategy": record["strategy"],
  100. "demand_id": record["demand_id"],
  101. "demand_name": record["demand_name"],
  102. "weight": normalize_scalar(record["weight"]),
  103. "type": record["type"],
  104. "video_count": record["video_count"],
  105. "video_list": parse_video_list(record["video_list"]),
  106. "extend": record["extend"],
  107. }
  108. )
  109. return rows