Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 按两个不同的分组求和_Sql_Sql Server_Sql Server 2005_Tsql - Fatal编程技术网

Sql 按两个不同的分组求和

Sql 按两个不同的分组求和,sql,sql-server,sql-server-2005,tsql,Sql,Sql Server,Sql Server 2005,Tsql,我从报告中得到了错误的结果。也许我错过了一些简单的事情 该报告是一个内联表值函数,它应该统计我们商店中的货物移动以及这些备件的索赔频率(在维修中更换) 问题:shop表中的不同sparepart(我们称之为SP)可以链接到“repair table”(TSP)中的同一sparepart。我需要SP中每个备件的货物移动和TSP中每个distinct备件的索赔计数 这是相关部分的一个非常简化的摘录: create table #tsp(id int, name varchar(20),claimed

我从报告中得到了错误的结果。也许我错过了一些简单的事情

该报告是一个内联表值函数,它应该统计我们商店中的货物移动以及这些备件的索赔频率(在维修中更换)

问题:shop表中的不同sparepart(我们称之为
SP
)可以链接到“repair table”(TSP)中的同一sparepart。我需要
SP
中每个备件的货物移动和
TSP
中每个distinct备件的索赔计数

这是相关部分的一个非常简化的摘录:

create table #tsp(id int, name varchar(20),claimed int);
create table #sp(id int, name varchar(20),fiTsp int,ordered int);

insert into #tsp values(1,'1235-6044',300);
insert into #tsp values(2,'1234-5678',400);

insert into #sp values(1,'1235-6044',1,30);
insert into #sp values(2,'1235-6044',1,40);
insert into #sp values(3,'1235-6044',1,50);
insert into #sp values(4,'1234-5678',2,60);

WITH cte AS(
    select tsp.id As TspID,tsp.name as TspName,tsp.claimed As Claimed
    ,sp.id As SpID,sp.name As SpName,sp.ordered As Ordered
    from #sp sp inner join #tsp tsp
    on sp.fiTsp=tsp.id
)
SELECT TspName, SUM(Claimed) As Claimed, Sum(Ordered) As Ordered
FROM cte
Group By TspName

drop table #tsp;
drop table #sp;
结果:

TspName       Claimed   Ordered
1234-5678       400       60
1235-6044       900       120
订购的
计数正确,但对于TspName='1235-6044',声称的
计数应为300而不是900

我需要根据
Tsp.ID
对索赔计数进行分组,并根据
Sp.ID
对订单计数进行分组。但如何在一个问题

编辑:实际上TVF看起来像(请注意,
getOrdered
getClaimed
是SVF,我在TSP的外部选择类别中分组):


解决方案

多亏了Aliostad,我通过先分组然后加入(实际TVF,减少到最小值)解决了这个问题:


您先加入,然后按分组。您需要将其反转,先分组,然后加入

在我的子查询中,我先分组,然后加入:

select 
    claimed,
    ordered 
from 
     #tsp 
inner JOIN
      (select 
             fitsp, 
             SUM(ordered) as ordered 
       from 
              #sp
        group by 
              fitsp) as SUMS           
on 
     SUMS.fiTsp = id;

您的
cte
tsp
sp
之间的内部连接,这意味着您要查询的数据如下所示:

SpID   Ordered   TspID   TspName     Claimed
1      30        1       1235-6044   300
2      40        1       1235-6044   300
3      50        1       1235-6044   300
4      60        2       1234-5678   400
注意
TspID
TspName
声明的
都是如何重复的。按
TspName
分组意味着将数据分为两组,一组用于
1235-6044
,另一组用于
1234-5678
。第一个组有3行运行聚合函数,第二个组只有一行。这就是为什么你的
金额(索赔)
会得到300*3=900


正如Aliostad所建议的,您应该首先按
TspID
分组,然后对
排序的
进行求和,然后加入
tsp
,我认为您只需要选择Claimed并将其添加到group by中,即可获得您想要的内容

WITH cte AS(
select tsp.id As TspID,tsp.name as TspName,tsp.claimed As Claimed
,sp.id As SpID,sp.name As SpName,sp.ordered As Ordered
from #sp sp inner join #tsp tsp
on sp.fiTsp=tsp.id )

SELECT TspName, Claimed, Sum(Ordered) As Ordered
FROM cte
Group By TspName, Claimed

无需加入,只需再次选择:

create table #tsp(id int, name varchar(20),claimed int);
create table #sp(id int, name varchar(20),fiTsp int,ordered int);

insert into #tsp values(1,'1235-6044',300);
insert into #tsp values(2,'1234-5678',400);

insert into #sp values(1,'1235-6044',1,30);
insert into #sp values(2,'1235-6044',1,40);
insert into #sp values(3,'1235-6044',1,50);
insert into #sp values(4,'1234-5678',2,60);

WITH cte AS(
    select tsp.id As TspID,tsp.name as TspName,tsp.claimed As Claimed
    ,sp.id As SpID,sp.name As SpName,sp.ordered As Ordered
    from #sp sp inner join #tsp tsp
    on sp.fiTsp=tsp.id
)

SELECT id, name, SUM(claimed) as Claimed, (SELECT SUM(ordered) FROM #sp WHERE #sp.fiTsp = #tsp.id GROUP BY #sp.fiTsp) AS Ordered
FROM #tsp
GROUP BY id, name

drop table #tsp;
drop table #sp;
CREATE FUNCTION [Gambio].[rptReusedStatistics](
     @fromDate datetime
    ,@toDate datetime
    ,@fromInvoiceDate datetime
    ,@toInvoiceDate datetime
    ,@idClaimStatus varchar(50)
    ,@idSparePartCategories varchar(1000)
    ,@idSpareParts varchar(1000)
)

RETURNS TABLE AS
RETURN(
    WITH ExclusionCat AS (
        SELECT idSparePartCategory AS ID From tabSparePartCategory
        WHERE idSparePartCategory IN(- 3, - 1, 6, 172,168)
    ), ReportSP AS (
        SELECT fiTabSparePart
        ,Inventory
        ,Gambio.getGoodsIn(idSparePart,@FromDate,@ToDate) GoodsIn
        ,Gambio.getOrdered(idSparePart,@FromDate,@ToDate) Ordered
        FROM  Gambio.SparePart
    ), ReportTSP AS (
        SELECT TSP.idSparePart
        ,Cat.SparePartCategoryName AS Category
        ,TSP.SparePartDescription AS Part
        ,TSP.SparePartName AS PartNumber
        ,CASE WHEN TSP.idSparePart IS NULL THEN 0 ELSE
            Gambio.getClaimed(TSP.idSparePart,@FromInvoiceDate,@ToInvoiceDate,@idClaimStatus,1)END AS ClaimedReused
        ,CASE WHEN TSP.idSparePart IS NULL THEN 0 ELSE
            Gambio.getCostSaving(TSP.idSparePart,@FromInvoiceDate,@ToInvoiceDate,@idClaimStatus)END AS Costsaving
        FROM  tabSparePart AS TSP 
        INNER JOIN tabSparePartCategory AS Cat 
        ON Cat.idSparePartCategory=TSP.fiSparePartCategory
        WHERE Cat.idSparePartCategory NOT IN(SELECT ID FROM ExclusionCat)
        AND (@idSparePartCategories IS NULL 
            OR TSP.fiSparePartCategory IN(
                SELECT Item From dbo.Split(@idSparePartCategories,',')
            )
        )
        AND (@idSpareParts IS NULL 
            OR TSP.idSparePart IN(
                SELECT Item From dbo.Split(@idSpareParts,',')
            )
        )
    )       
    SELECT Category
    --, Part
    --, PartNumber
    , (SELECT SUM(Inventory) FROM ReportSP WHERE ReportSP.fiTabSparePart = idSparePart GROUP BY fiTabSparePart) AS Inventory
    , (SELECT SUM(GoodsIn) FROM ReportSP WHERE ReportSP.fiTabSparePart = idSparePart GROUP BY fiTabSparePart) AS GoodsIn
    , (SELECT SUM(Ordered) FROM ReportSP WHERE ReportSP.fiTabSparePart = idSparePart GROUP BY fiTabSparePart) AS Ordered
    , Claimed
    , ClaimedReused
    , Costsaving
    , Count(*) AS PartCount
    FROM ReportTSP
    GROUP BY Category
)
产生:

id  name        Claimed Ordered 
1   1235-6044   300 120 
2   1234-5678   400 60
--编辑--

根据附加信息,我可能会尝试按照示例分割CTE以形成数据。我完全承认Aliostad的方法可能会产生更清晰的查询,但这里有一个尝试(完全盲目)使用subselect:

create table #tsp(id int, name varchar(20),claimed int);
create table #sp(id int, name varchar(20),fiTsp int,ordered int);

insert into #tsp values(1,'1235-6044',300);
insert into #tsp values(2,'1234-5678',400);

insert into #sp values(1,'1235-6044',1,30);
insert into #sp values(2,'1235-6044',1,40);
insert into #sp values(3,'1235-6044',1,50);
insert into #sp values(4,'1234-5678',2,60);

WITH cte AS(
    select tsp.id As TspID,tsp.name as TspName,tsp.claimed As Claimed
    ,sp.id As SpID,sp.name As SpName,sp.ordered As Ordered
    from #sp sp inner join #tsp tsp
    on sp.fiTsp=tsp.id
)

SELECT id, name, SUM(claimed) as Claimed, (SELECT SUM(ordered) FROM #sp WHERE #sp.fiTsp = #tsp.id GROUP BY #sp.fiTsp) AS Ordered
FROM #tsp
GROUP BY id, name

drop table #tsp;
drop table #sp;
CREATE FUNCTION [Gambio].[rptReusedStatistics](
     @fromDate datetime
    ,@toDate datetime
    ,@fromInvoiceDate datetime
    ,@toInvoiceDate datetime
    ,@idClaimStatus varchar(50)
    ,@idSparePartCategories varchar(1000)
    ,@idSpareParts varchar(1000)
)

RETURNS TABLE AS
RETURN(
    WITH ExclusionCat AS (
        SELECT idSparePartCategory AS ID From tabSparePartCategory
        WHERE idSparePartCategory IN(- 3, - 1, 6, 172,168)
    ), ReportSP AS (
        SELECT fiTabSparePart
        ,Inventory
        ,Gambio.getGoodsIn(idSparePart,@FromDate,@ToDate) GoodsIn
        ,Gambio.getOrdered(idSparePart,@FromDate,@ToDate) Ordered
        FROM  Gambio.SparePart
    ), ReportTSP AS (
        SELECT TSP.idSparePart
        ,Cat.SparePartCategoryName AS Category
        ,TSP.SparePartDescription AS Part
        ,TSP.SparePartName AS PartNumber
        ,CASE WHEN TSP.idSparePart IS NULL THEN 0 ELSE
            Gambio.getClaimed(TSP.idSparePart,@FromInvoiceDate,@ToInvoiceDate,@idClaimStatus,1)END AS ClaimedReused
        ,CASE WHEN TSP.idSparePart IS NULL THEN 0 ELSE
            Gambio.getCostSaving(TSP.idSparePart,@FromInvoiceDate,@ToInvoiceDate,@idClaimStatus)END AS Costsaving
        FROM  tabSparePart AS TSP 
        INNER JOIN tabSparePartCategory AS Cat 
        ON Cat.idSparePartCategory=TSP.fiSparePartCategory
        WHERE Cat.idSparePartCategory NOT IN(SELECT ID FROM ExclusionCat)
        AND (@idSparePartCategories IS NULL 
            OR TSP.fiSparePartCategory IN(
                SELECT Item From dbo.Split(@idSparePartCategories,',')
            )
        )
        AND (@idSpareParts IS NULL 
            OR TSP.idSparePart IN(
                SELECT Item From dbo.Split(@idSpareParts,',')
            )
        )
    )       
    SELECT Category
    --, Part
    --, PartNumber
    , (SELECT SUM(Inventory) FROM ReportSP WHERE ReportSP.fiTabSparePart = idSparePart GROUP BY fiTabSparePart) AS Inventory
    , (SELECT SUM(GoodsIn) FROM ReportSP WHERE ReportSP.fiTabSparePart = idSparePart GROUP BY fiTabSparePart) AS GoodsIn
    , (SELECT SUM(Ordered) FROM ReportSP WHERE ReportSP.fiTabSparePart = idSparePart GROUP BY fiTabSparePart) AS Ordered
    , Claimed
    , ClaimedReused
    , Costsaving
    , Count(*) AS PartCount
    FROM ReportTSP
    GROUP BY Category
)

如果不更好地理解整个模式,就很难涵盖所有可能发生的情况,但这是否有效(我怀疑所有实例的PartCount都是1)希望它能为您提供一些新的思路来选择其他方法。

MAX
对我没有帮助,因为它只对这个小样本数据有效,而不适用于我在SparePartCategories(TSP属于一个类别)上分组的整个查询。我需要索赔单上的金额通常也是正确的。谢谢。我在问题中没有提到它,但实际上我通过标量值函数得到了顺序计数和索赔计数。第一个将SP.ID作为参数,第二个将TSP.ID作为参数。因此,我需要一个CTE,它将所有SP传递给
getOrdered
,将所有不同的TSP传递给
getClaimed
。所以我不能在这个CTE中进行子选择,因为它不是计算它的位置(实际上它并没有那么简单)。
SUM
将应用于使用CTE和类别分组的外部选择(每个TSP属于一个类别)。@TimSchmelter标量函数是一成不变的吗?根据我对结构的理解,SP.id是不相关的,您应该能够将TSP.id传递给两者。恐怕它们都是,实际上计算要困难得多。订单计数和索赔计数都不是这些表中的列,但必须根据其他事实表中给定的时间跨度、状态和重用标志进行计算。因此我创建了这些标量函数。所以我试着用这个简化的例子来概括这个问题。我能想到的最简单的选择就是按照这个例子,创建两个表。将您的
报告
查询分为两个查询,生成一个SP记录表和一个TSP订单表,然后最后一个阶段可以按照I或Aliostad指示进行分组。感谢您提供两个查询的示例。但最后,我成功地将Aliostad的方法应用到我的TVF中(请参见我的编辑),它工作完美,速度足够快。谢谢。在我把你的建议带到我的TVF(看看我的编辑)后,它工作得非常好。很高兴听到它都被修复了。
CREATE FUNCTION [Gambio].[rptReusedStatistics](
     @fromDate datetime
    ,@toDate datetime
    ,@fromInvoiceDate datetime
    ,@toInvoiceDate datetime
    ,@idClaimStatus varchar(50)
    ,@idSparePartCategories varchar(1000)
    ,@idSpareParts varchar(1000)
)

RETURNS TABLE AS
RETURN(
    WITH ExclusionCat AS (
        SELECT idSparePartCategory AS ID From tabSparePartCategory
        WHERE idSparePartCategory IN(- 3, - 1, 6, 172,168)
    ), ReportSP AS (
        SELECT fiTabSparePart
        ,Inventory
        ,Gambio.getGoodsIn(idSparePart,@FromDate,@ToDate) GoodsIn
        ,Gambio.getOrdered(idSparePart,@FromDate,@ToDate) Ordered
        FROM  Gambio.SparePart
    ), ReportTSP AS (
        SELECT TSP.idSparePart
        ,Cat.SparePartCategoryName AS Category
        ,TSP.SparePartDescription AS Part
        ,TSP.SparePartName AS PartNumber
        ,CASE WHEN TSP.idSparePart IS NULL THEN 0 ELSE
            Gambio.getClaimed(TSP.idSparePart,@FromInvoiceDate,@ToInvoiceDate,@idClaimStatus,1)END AS ClaimedReused
        ,CASE WHEN TSP.idSparePart IS NULL THEN 0 ELSE
            Gambio.getCostSaving(TSP.idSparePart,@FromInvoiceDate,@ToInvoiceDate,@idClaimStatus)END AS Costsaving
        FROM  tabSparePart AS TSP 
        INNER JOIN tabSparePartCategory AS Cat 
        ON Cat.idSparePartCategory=TSP.fiSparePartCategory
        WHERE Cat.idSparePartCategory NOT IN(SELECT ID FROM ExclusionCat)
        AND (@idSparePartCategories IS NULL 
            OR TSP.fiSparePartCategory IN(
                SELECT Item From dbo.Split(@idSparePartCategories,',')
            )
        )
        AND (@idSpareParts IS NULL 
            OR TSP.idSparePart IN(
                SELECT Item From dbo.Split(@idSpareParts,',')
            )
        )
    )       
    SELECT Category
    --, Part
    --, PartNumber
    , (SELECT SUM(Inventory) FROM ReportSP WHERE ReportSP.fiTabSparePart = idSparePart GROUP BY fiTabSparePart) AS Inventory
    , (SELECT SUM(GoodsIn) FROM ReportSP WHERE ReportSP.fiTabSparePart = idSparePart GROUP BY fiTabSparePart) AS GoodsIn
    , (SELECT SUM(Ordered) FROM ReportSP WHERE ReportSP.fiTabSparePart = idSparePart GROUP BY fiTabSparePart) AS Ordered
    , Claimed
    , ClaimedReused
    , Costsaving
    , Count(*) AS PartCount
    FROM ReportTSP
    GROUP BY Category
)