Продолжение: как передать переменную для выбора блока? - PullRequest
0 голосов
/ 09 ноября 2018

Мне нужно рассчитать количество пользователей внутри запроса выбора. Вот мой SQL-фрагмент

SELECT count(id) FROM demo.users WHERE year_id = 'c4c62a9d-801f-4573-92a8-aa0a8589200a'

Я использую его внутри

   CASE count(DISTINCT assigned_lessons.id)
     WHEN 0 THEN 0
     ELSE count(DISTINCT homework_results.id) :: float /
          (
            count(DISTINCT assigned_lessons.id) *
            (SELECT count(id) FROM demo.users WHERE year_id = 'c4c62a9d-801f-4573-92a8-aa0a8589200a')
          )
       END AS completed_homework_rate

Вот моя реализация на сиквеле, которая работает

        Sequel.case({ 0 => 0 },
          Sequel.cast(count(:homework_results__id).distinct, :float) /
            (
              count(:assigned_lessons__id).distinct *
                DB['demo__users'.to_sym].select do
                  count(id)
                end.where(year_id: 'c4c62a9d-801f-4573-92a8-aa0a8589200a')
            ),
          count(:assigned_lessons__id).distinct,
        ).as(:completed_homework_rate),

но мне нужно использовать что-то вроде этого

        Sequel.case({ 0 => 0 },
          Sequel.cast(count(:homework_results__id).distinct, :float) /
            (
              count(:assigned_lessons__id).distinct *
                DB["#{schema}__users".to_sym].select do
                  count(id)
                end.where(year_id: year.id)
            ),
          count(:assigned_lessons__id).distinct,
        ).as(:completed_homework_rate),

Мне нужно использовать schema и year varibale внутри запроса, но Сиквел скажет мне

undefined method `id' for #<Sequel::SQL::Identifier @value=>:year>

или если я передаю идентификатор года непосредственно в виде строки, он заменяет schema переменную неправильно

SELECT count("id") FROM "#<Sequel::SQL::Identifier:0x00007f8d36b553b8>"."users"

Упрощенный вариант использования

  DB[:curriculum_strands].select do
      [
        Sequel.case({ 0 => 0 },
          Sequel.cast(count(:homework_results__id).distinct, :float) /
            (
              count(:assigned_lessons__id).distinct *
                DB["#{schema}__users".to_sym].select do
                  count(id)
                end.where(year_id: year.id)
            ),
          count(:assigned_lessons__id).distinct,
        ).as(:completed_homework_rate),
      ]
    end.left_join(...)

Есть ли способ передать переменные в блок выбора в этом случае?

1 Ответ

0 голосов
/ 09 ноября 2018

Я обнаружил, что мне не нужно использовать блокировку select.

Вот мое решение

  DB[:curriculum_strands].select(
      completed_homework_rate.as(:completed_homework_rate),
    ).left_join(...)

private

def completed_homework_rate
  Sequel.case({ 0 => 0 },
    count_distinct(:homework_results__id).cast(Float) /
      (count_distinct(:assigned_lessons__id) * users_count),
    count_distinct(:assigned_lessons__id),
  )
end

def users_count
  DB["#{schema}__users".to_sym].select { count(id) }.where(year_id: year.id)
end

def count_distinct(column)
  Sequel.function(:count, column).distinct
end

Идеи по улучшению этого кода принимаются ...)

...