SQL-запрос для получения результатов на основе агрегатного условия (сумма столбца) - PullRequest
2 голосов
/ 29 декабря 2011

У меня есть такая таблица:

Product   sl_no Wt_Kg
Prod-001    1   3.000
Prod-002    2   4.000
Prod-003    3   2.000
Prod-004    4   3.000
Prod-005    5   6.000
Prod-006    6   7.000
Prod-007    7   1.000
Prod-008    8   2.000
Prod-009    9   3.000
Prod-010    10  5.000
Prod-011    11  2.000
Prod-012    12  4.000

Мне нужны все записи из этой таблицы, начиная с порядкового номера и до достижения указанной суммы веса в килограммах.
Например, если я хочу получить все продукты с серийным номером (Sl_no) 1, имеющие сумму веса, меньшую или равную 25 кг, я должен получить следующий результат:

Product   sl_no Wt_Kg
Prod-001    1   3.000
Prod-002    2   4.000
Prod-003    3   2.000
Prod-004    4   3.000
Prod-005    5   6.000
Prod-006    6   7.000

В следующем примере, если я хочу, чтобы все продукты начинались с серийного номера 3 и весили не более 30 кг, я должен получить следующий результат:

Product   sl_no Wt_Kg
Prod-003    3   2.000
Prod-004    4   3.000
Prod-005    5   6.000
Prod-006    6   7.000
Prod-007    7   1.000
Prod-008    8   2.000
Prod-009    9   3.000
Prod-010    10  5.000

Пожалуйста, помогите мне достичь этого. Заранее спасибо ...

Ответы [ 4 ]

3 голосов
/ 29 декабря 2011

Это может быть более эффективным.Я начал с создания таблицы с именем _test в моей базе данных, соответствующей вашему описанию.Это решение использует возможность увеличения значения в статистике UPDATE (http://haacked.com/archive/2004/02/28/sql-auto-increment.aspx).. Прекращает увеличение после достижения целевого значения. Производительность будет проблемой, если у вас есть миллионы продуктов, но вы можете предположить, чточто вы достигнете своего целевого веса в пределах определенного количества продуктов (на основе среднего веса) и будете использовать SET ROW_COUNT, чтобы ограничить начальное количество записей в табличной переменной.

DECLARE @Weight            REAL
DECLARE @SerialNumber      INT
DECLARE @MaxWeight         REAL

SET @Weight                = 0
SET @SerialNumber          = 3
SET @MaxWeight             = 30

DECLARE @Results TABLE
        (
        Product           CHAR(8),
        sl_no             INT,
        Wt_Kg             REAL,
        Total_Wt          REAL
        )

INSERT INTO
        @Results

(
        Product,
        sl_no,
        Wt_KG
)

SELECT
        Product,
        sl_no,
        Wt_KG

FROM
        _test

WHERE
        sl_no >= @SerialNumber  

ORDER BY
        sl_no


UPDATE
        @Results

SET 
        @Weight = Total_Wt = Wt_Kg + @Weight

WHERE 
        @Weight <= @MaxWeight


SELECT
        *

FROM 
        @Results

WHERE 
        Total_Wt <= @MaxWeight

Результатами являются:

Product  sl_no       Wt_Kg         Total_Wt
-------- ----------- ------------- -------------
Prod-003 3           2             2
Prod-004 4           3             5
Prod-005 5           6             11
Prod-006 6           7             18
Prod-007 7           1             19
Prod-008 8           2             21
Prod-009 9           3             24
Prod-010 10          5             29
1 голос
/ 29 декабря 2011
declare @total decimal(9,3), @sl_no int
select @total = 25.000, @sl_no = 0 -- first case
--select @total = 30.000, @sl_no = 3 -- second case

;with tab (Product, sl_no, Wt_Kg) as (
    select 'Prod-001', 1, 3.000 union all
    select 'Prod-002', 2, 4.000 union all
    select 'Prod-003', 3, 2.000 union all
    select 'Prod-004', 4, 3.000 union all
    select 'Prod-005', 5, 6.000 union all
    select 'Prod-006', 6, 7.000 union all
    select 'Prod-007', 7, 1.000 union all
    select 'Prod-008', 8, 2.000 union all
    select 'Prod-009', 9, 3.000 union all
    select 'Prod-010', 10, 5.000 union all
    select 'Prod-011', 11, 2.000 union all
    select 'Prod-012', 12, 4.000
)
select t3.*
from tab t3
join (
    select t1.product, t1.sl_no, sum(t2.Wt_Kg) as total
    from tab t1
    join tab t2 on t1.sl_no >= t2.sl_no
    where t2.sl_no >= @sl_no
    group by t1.product, t1.sl_no
) t on t.product = t3.product and t.sl_no = t3.sl_no
where t.total <= @total

Добавлено : группировка и объединение по sl_no (на тот случай, если product не является уникальным)

Результаты в первом случае:

Product sl_no   Wt_Kg
Prod-001    1   3.000
Prod-002    2   4.000
Prod-003    3   2.000
Prod-004    4   3.000
Prod-005    5   6.000
Prod-006    6   7.000

второй случай:

Product sl_no   Wt_Kg
Prod-003    3   2.000
Prod-004    4   3.000
Prod-005    5   6.000
Prod-006    6   7.000
Prod-007    7   1.000
Prod-008    8   2.000
Prod-009    9   3.000
Prod-010    10  5.000
1 голос
/ 29 декабря 2011

Мое решение:

declare @total decimal(9,3), @sl_no int
select @total = 25.000, @sl_no = 1 -- first case


select * from Tab where sl_no<=
(
    select MAX(sl_no3) from (
        select t3.sl_no sl_no3, sum(t3.Wt_kg) Wt_kg3 from (
            select t1.sl_no sl_no, t2.Wt_Kg as Wt_kg from Tab t1, Tab t2 where t1.sl_no>=t2.sl_no and t2.sl_no >=@sl_no
        ) t3 group by t3.sl_no having SUM(t3.Wt_kg) <= @total
    ) t4
) and sl_no>=$sl_no
0 голосов
/ 29 декабря 2011

Если серийный номер уникален:

Первый пример:

select *
from tableName
where sl_no >= 1
and Wt_Kg <= 25

Второй пример:

select *
from tableName
where sl_no >= 3
and Wt_Kg <= 30

Если серийный номер не является уникальным:

select Product, sl_no, Sum(Wt_Kg)
from tableName
where Wt_Kg <= 25
group by Product, sl_no

EDIT

Если вы хотите отфильтровать результаты по суммированному значению, вы можете попробовать это:

select Product, sl_no, Sum(Wt_Kg)
from tableName
group by Product, sl_no
having (Sum(Wt_Kg) <= 25)

Имейте в виду, что если Product ИЛИ sl_no уникальны, то Sum () не имеет смысла, поскольку агрегат используется для записей, которые имеют определенные значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...