PostgreSQL json_agg 排序和性能

问题描述 投票:0回答:0

我在使用 SQL 生成 JSON 时遇到了一些困难。

  1. 如果我尝试按 exercise_instruction.rankinstructions 值进行排名,结果重复 3 次。我有 3 个 json 输出。有没有不重复排序的方法?

当使用 ORDER BY exercise_instruction.rank 结果看起来像

  1. 查询中数据重复多次。如果不使用 DISTINCT,指令将返回 9 个值而不是 3 个。这会产生性能问题吗?

  1. 是否有已知的更好的方法来构建具有更高性能的查询?
with activities_result AS (
  SELECT
    activities.id,
    json_strip_nulls(
      json_build_object (
        'id',
        activities.id,
        'activity_type',
        activities.activity_type,
        'exercise_id',
        activities.exercise_id,
        'exercise_type',
        exercises.exercise_type,
        'name',
        exercises.name,
        'videos',
        json_agg(
          DISTINCT jsonb_build_object(
            'id',
            exercise_video_assets.id,
            'url',
            exercise_video_assets.url,
            'quality',
            exercise_video_assets.quality,
            'asset_type',
            exercise_video_assets.asset_type
          )
        ) FILTER (
          WHERE
            exercise_video_assets.id IS NOT NULL
        ),
        'instructions',
        json_agg(  -- Order by exercise_instruction.rank:
          DISTINCT jsonb_build_object (
            'id',
            instructions.id,
            'detail',
            instructions.detail,
            'rank',
            exercise_instruction.rank
          )
        ) FILTER (
          WHERE
            instructions.id IS NOT NULL
        ),
        'images',
        json_agg(
          DISTINCT jsonb_build_object(
            'id',
            exercise_image_assets.id,
            'url',
            exercise_image_assets.url,
            'quality',
            exercise_image_assets.quality,
            'asset_type',
            exercise_image_assets.asset_type,
            'width',
            exercise_image_assets.width,
            'height',
            exercise_image_assets.height
          )
        ) FILTER (
          WHERE
            exercise_image_assets.id IS NOT NULL
        ),
        'name_cue',
        json_build_object (
          'id',
          exercise_audio_assets.id,
          'url',
          exercise_audio_assets.url,
          'asset_type',
          exercise_audio_assets.asset_type,
          'delay',
          exercise_audio_assets.delay,
          'duration',
          exercise_audio_assets.duration
        ),
        'volume',
        json_build_object(
          'id',
          volumes.id,
          'volume_type',
          volumes.volume_type,
          'time',
          volumes.time,
          'volume_cue',
          CASE WHEN volume_audio_assets.id IS NULL THEN NULL ELSE json_build_object (
            'id',
            volume_audio_assets.id,
            'url',
            volume_audio_assets.url,
            'asset_type',
            volume_audio_assets.asset_type,
            'delay',
            volume_audio_assets.delay,
            'duration',
            volume_audio_assets.duration
          ) END
        )
      )
    ) as activities
  FROM
    activities
    INNER JOIN exercises ON exercises.id = activities.exercise_id
    INNER JOIN volumes ON volumes.id = activities.volume_id
    LEFT JOIN exercise_audio_assets ON exercises.name_cue_id = exercise_audio_assets.id
    LEFT JOIN exercise_video_assets ON exercises.id = exercise_video_assets.exercise_id
    LEFT JOIN exercise_image_assets ON exercises.id = exercise_image_assets.exercise_id
    LEFT JOIN exercise_instruction ON exercises.id = exercise_instruction.exercise_id 
    LEFT JOIN instructions ON exercise_instruction.instruction_id = instructions.id
    LEFT JOIN volume_audio_assets ON volumes.id = volume_audio_assets.volume_id
  GROUP BY
    activities.id,
    exercises.exercise_type,
    exercises.name,
    exercise_audio_assets.id,
    volumes.id,
    volume_audio_assets.id
)
SELECT * FROM activities_result WHERE activities_result.id = 2

输出看起来像这样:

{
  "id": 2,
  "activity_type": "ex",
  "exercise_id": 1,
  "exercise_type": "ex",
  "name": "Exercise Name",
  "videos": [
    {
      "id": 1,
      "url": "***",
      "quality": "low",
      "asset_type": "video"
    },
    {
      "id": 2,
      "url": "***",
      "quality": "medium",
      "asset_type": "video"
    },
    {
      "id": 3,
      "url": "***",
      "quality": "high",
      "asset_type": "video"
    }
  ],
  "instructions": [
    {
      "id": 3,
      "rank": 0,
      "detail": "text1"
    },
    {
      "id": 4,
      "rank": 1,
      "detail": "text2"
    },
    {
      "id": 5,
      "rank": 2,
      "detail": "text3"
    }
  ],
  "images": [
    {
      "id": 1,
      "url": "***",
      "quality": "low",
      "asset_type": "image"
    },
    {
      "id": 2,
      "url": "***",
      "quality": "medium",
      "asset_type": "image"
    },
    {
      "id": 3,
      "url": "***",
      "quality": "high",
      "asset_type": "image"
    }
  ],
  "name_cue": {
    "id": 1,
    "url": "***",
    "asset_type": "audio",
    "delay": 0,
    "duration": 1.46
  },
  "volume": {
    "id": 1,
    "volume_type": "time",
    "time": 45
  }
}

sql postgresql database-design aggregate-functions postgresql-performance
© www.soinside.com 2019 - 2024. All rights reserved.