Избегайте групповых предложений или агрегатных функций в MS SQL Server - PullRequest
0 голосов
/ 06 сентября 2018

Я использую агрегатные функции / group by в своем запросе, но не получаю искомый вывод. У моего table есть много столбцов, но только для целей тестирования, я показываю ниже пример -

Supplier Table -

SpID    SupName   
1       Test
2       Test2
3       Test3   

Stock Table (has more columns) -

SID      ReplaceID   SupID     Qty      PName   PSize
1          11           1       2         P1x    5-6
2                       2       5         P2     11Y
11                      1       4         P1     6Y
11                      1       7         P1     6Y
12                      3       10        P12    1-2

Вывод, который я ищу, т.е. когда Supplier ID равно 1, мне нужно присоединиться к SID and ReplaceID Qty и показать, что значения ID не имеют ReplaceID.

Я хочу ниже вывода -

ID  OldID  SupName  PNAME    PSize  Qty         
11    1      Test     P1      6Y    13

Но получается ниже выхода -

ID  OldID   SupName PName   PSize   Qty
11  NULL      Test   P1      6Y      11
11  1         Test   P1x     5-6     2

Мой запрос -

; with
cte as
(
    -- Replace ID
    select ID = ReplaceID, OldID=SID, PName, PSize, SupID, TotalQty = SUM(QTY)
    from Stock ST
    where exists
        (
            select *
            from Stock s
            where s.SID = ST.ReplaceID
        )
    group by ReplaceID, SID, PName, PSize, SupID

    union all

    -- without Replace ID
    select ID = SID, NULL AS OldID, PName, PSize, SupID, TotalQty = SUM(QTY)
    from Stock ST
    where not exists
        (
            select *
            from Stock s
            where s.SID = ST.ReplaceID
        )
    group by SID, PName, PSize, SupID
)
select  c.ID, c.OldID, SP.SupName, PName, PSize, Qty = SUM(TotalQty)
from    cte c
        inner join Supplier SP on c.SupID = SP.SpID
where   c.SupID = 1
group by c.ID, c.OldID, SupName, PName, PSize
order by c.ID

Может кто-нибудь, пожалуйста, помогите мне, как я могу этого достичь. Я предпочитаю не использовать агрегатные функции, если это возможно.

Спасибо

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Это дает результат, который вы просили, и, по крайней мере, устраняет некоторые сложности:

declare @suppliers table (SpID int not null, SupName varchar(10) not null)
insert into @suppliers(SpID,SupName) values
(1,'Test '),
(2,'Test2'),
(3,'Test3')

declare @stock table (SID int not null, ReplaceID int null, SupID int not null,
Qty int not null, PName varchar(10) not null, PSize varchar(10) not null)
insert into @stock(SID,ReplaceID,SupID,Qty,PName,PSize) values
(1 ,11  ,1,2 ,'P1x','5-6'),
(2 ,null,2,5 ,'P2 ','11Y'),
(11,null,1,4 ,'P1 ','6Y '),
(11,null,1,7 ,'P1 ','6Y '),
(12,null,3,10,'P12','1-2')

declare @SupID int
set @SupID = 1

select
    COALESCE(st2.SID,st1.SID) as SID,
    MAX(CASE WHEN st1.ReplaceID is not null then st1.SID END) as OldID,
    sp.SupName,
    COALESCE(st2.PName,st1.PName) as PName,
    COALESCE(st2.PSize,st1.PSize) as PSize,
    SUM(Qty) as Qty
from
    @suppliers sp
        inner join
    @stock st1
        on
            sp.SpID = st1.SupID
        left join
    (select SID,SupID,MAX(PName) as PName,MAX(PSize) as PSize from @stock 
     GROUP By SID,SupID) st2
        on
            sp.SpID = st2.SupID and
            st2.SID = st1.ReplaceID
where
    sp.SPID = @SupID
group by
    COALESCE(st2.SID,st1.SID),
    sp.SupName,
    COALESCE(st2.PName,st1.PName),
    COALESCE(st2.PSize,st1.PSize)

Результат:

SID         OldID       SupName    PName      PSize      Qty
----------- ----------- ---------- ---------- ---------- -----------
11          1           Test       P1         6Y         13

Как я уже говорил, нам нужно использовать некоторую агрегацию, чтобы получить Qty. И это основывается на предположении, что PName и PSize уникальны для каждого значения SID (что указывает на плохую нормализацию). Я также предположил, что ReplacementID поставляется от того же поставщика, что и оригинал.


Альтернативная формулировка, приведенная выше, делает SUM(Qty) в подзапросе st2 (так как мы все равно уже собираемся там), делает Qty во внешнем st1.Qty + COALESCE(st2.Qty,0), удаляет MAX вокруг OldID выражение и может затем устранить внешнее GROUP BY. Тем не менее, вышеизложенное было моим первым взятием и прочтением «чище» для меня.

0 голосов
/ 06 сентября 2018

Это полезно ??

    Create Table #Supplier(SpID int,SupName Varchar(100))
    Create Table #Stock([SID] int,ReplaceID int, SupID int,Qty int,PName varchar(100), PSize varchar(100))

    Insert Into #Supplier
    SELECT 1,'Test' Union All
    SELECT 2,'Test2' Union All
    SELECT 3,'Test3'   


    Insert Into #Stock
    SELECT 1,11  ,1,2,'P1x','5-6' Union All
    SELECT 2,NULL,2,5,'P2','11Y' Union All
    SELECT 11,NULL,1,4,'P1','6Y' Union All
    SELECT 11,NULL,1,7,'P1','6Y' Union All
    SELECT 12,NULL,3,10,'P12','1-2'

    ;with cte1
    As

    (
    Select ISNULL(st.ReplaceID,SpID) As ID, SpID As OldID, SupName,
     ISNULL(strp.PName,st.PName) PName,ISNULL(strp.PSize,st.PSize) PSize,SUM(ISNULL(strp.Qty,0)) as Qty
    from #Supplier sp
    LEFT JOIN #Stock st on sp.SpID=st.SID
    LEFT JOIN #Stock strp on st.ReplaceID=strp.SID
    Group by ISNULL(st.ReplaceID,SpID) , SpID , SupName,ISNULL(strp.PName,st.PName),ISNULL(strp.PSize,st.PSize)
    )
    ,cte2
    As
    (
    Select ISNULL(st.ReplaceID,SpID) As ID, SpID As OldID, SupName,st.Qty  
    from #Supplier sp
    LEFT JOIN #Stock st on sp.SpID=st.SID
    Where ReplaceId is Not NULL And ReplaceID!=''
    )

    Select c1.id,c1.OldID, c1.SupName, c1.PName,c1.PSize,c1.Qty+c2.Qty As Qty
    from cte1 c1
    Left JOIN cte2 c2 on c1.Id=c2.id and c1.OldID=c2.OldID
    order by OldID


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