SQL распределяет значения по строкам


SQL-это не моя сильная сторона, и мне нужна помощь. Я пытаюсь распределить максимальное значение, которое я выбираю из таблицы, по нескольким строкам. Допустим, я начинаю с максимального значения 5 (B.MaxVal = 5), и у меня есть 3 строки, которые нужно разбить (есть 3 экземпляра одного и того же B.bId).

Я хочу взять значение 5 и вывести результат каждого из этих экземпляров, получая что-то. Если мы возьмем значение 5 и разделим его на 3, я получу поплавок, который не является хорошим. Вместо этого я хотел бы, чтобы 5, чтобы получить распространяется как 2, 2, 1 в 3 экземплярах B. bId

select distinct 
    A.aId,  B.bId, B.MaxVal, 
    B.MaxVal / Count(B.bId) OVER(PARTITION BY B.bId) AS 'AVG' 
from 
    CPN
inner join 
    PN on CPN.aId = PN.id
inner join 
    A on A.aId = CPN.aId
left join 
    B on PN.bId = B.bId
where 
    (some search param)
group by 
    A.aId,  B.bId, B.MaxVal

A и B-это разные таблицы.

1 2

1 ответ:

EDIT: изменено для использования функции FLOOR() и изменено Неравенство для вашего комментария.

Я бы попробовал что-то вроде этого:

FLOOR(B.MaxVal / COUNT(B.bId) OVER (PARTITION BY B.bId)) 
+ CASE 
    WHEN ROW_NUMBER() OVER (PARTITION BY b.bId ORDER BY b.bId) <= (B.MaxVal % COUNT(B.bId) OVER (PARTITION BY B.bId)) THEN 1 
    ELSE 0 
END as "DISTRIBUTED_AVG"
Первый бит-это деление, которое вы уже делали. ROUND() в SQL Server также выполняет функцию усечения . ROUND(<expression>,0,1) усечет значение в десятичной точке. используйте функцию FLOOR().

Следующий бит сложен. Ваше описание в основном состоит в том, что нам нужно разложить оставшуюся часть деление максимума на количество. Ну, остаток от деления - это функция по модулю. Итак, мы знаем, что нам, вероятно, нужно использовать это. Вот что такое (B.MaxVal % COUNT(B.bId) OVER (PARTITION BY B.bId)).

Далее, нам нужно каким-то образом узнать, сколько из остатка мы израсходовали. Поскольку мы имеем дело только с остатком, мы знаем, что нам никогда не нужно давать больше одного дополнительного предмета для какой-либо ценности. Это также означает, что мы будем "потреблять" остаток из расчета 1 на строку. Итак, нам нужно знать, в каком ряду группы мы находимся. Делать для этого я использовал функцию ROW_NUMBER(). Он разделен так же, как и COUNT(), поэтому у него будет та же группировка. Единственное, что вы, возможно, захотите изменить, - это порядок; я просто выбрал что-то. В принципе, мы знаем, что когда остаток равен или меньше числа строк, через которые мы прошли, то у нас есть остаток, ну, оставшийся. Я чувствую, что моя математика немного не в порядке или я что-то упускаю, однако, потому что в настоящее время я немного устал. Я призываю вас посмотреть на каждую из них. из них индивидуально понять, что он делает:
SELECT DISTINCT A.aId,
    B.bId,
    B.MaxVal,
    B.MaxVal / Count(B.bId) OVER (PARTITION BY B.bId) AS 'AVG'
    FLOOR(B.MaxVal / COUNT(B.bId) OVER (PARTITION BY B.bId)), 
    ROW_NUMBER() OVER (PARTITION BY b.bId ORDER BY b.bId), 
    B.MaxVal % COUNT(B.bId) OVER (PARTITION BY B.bId),
    ROUND(B.MaxVal / COUNT(B.bId) OVER (PARTITION BY B.bId),0,1) 
    + CASE 
        WHEN ROW_NUMBER() OVER (PARTITION BY b.bId ORDER BY b.bId) <= (B.MaxVal % COUNT(B.bId) OVER (PARTITION BY B.bId)) THEN 1 
        ELSE 0 
    END as "DISTRIBUTED_AVG"
FROM [...]