количество строк, максимальное значение которых меньше указанного параметра - PullRequest
1 голос
/ 16 апреля 2020

Я хочу найти в своей таблице максимальное значение, которое меньше указанного в параметре, и получить количество строк, имеющих то же значение, что и максимальное значение. Например, в моей таблице есть значения: (4,1,3,1,4,4,10), и это список параметров в строке "2,9,10,4". Я должен разделить строку для разделения параметров. Основываясь на этом примере значений, я хочу получить что-то вроде этого:

param | max value | count
2     | 1         | 2
9     | 4         | 3
10    | 4         | 3
4     | 3         | 1

И это мой пример запроса:

select
[param]
, max([val]) [max_value_by_param]
, max(count) [count]
from(
    select
    n.value as [param]
    ,a.val
    , count(*) as [count]   
    from (--mock of table
        select 1 as val union all
        select 3 as val union all
        select 4 as val union all
        select 1 as val union all
        select 3 as val union all
        select 4 as val union all
        select 4 as val union all
        select 10 as val
    ) a
    join (select [value] from string_split('2,9,10,4', ',')) n--list of params
        on a.val < n.[value]
    group by n.value, a.val
) tmp
group by [param]

Можно ли сделать это лучше / проще?

1 Ответ

1 голос
/ 16 апреля 2020

Вот способ express с использованием apply:

select s.value as param, a.val, a.cnt
from string_split('2,9,10,4', ',') s outer apply
     (select top (1) a.val, count(*) as cnt
      from a
      group by a.val
      having a.val < s.value
      order by a.val desc
     ) a;

Здесь - это скрипта db <>.

Но самый быстрый метод вероятно, будет следующим:

with av as (
      select a.val, count(*) as cnt
      from a
      group by a.val
      union all
      select s.value, null as cnt
      from string_split('2,9,10,4', ',') s
     )
select val, a_val, a_cnt
from (select av.*,
             max(case when cnt is not null then val end) over (order by val, (case when cnt is null then 1 else 2 end)) as a_val,
             max(case when cnt is not null then cnt end) over (order by val, (case when cnt is null then 1 else 2 end)) as a_cnt
      from av
     ) av
where cnt is null;

Это объединяет данные только один раз и должно возвращать все параметры, даже те, которые не имеют предшествующих значений в a.

...