2017-01-03 54 views
1

所以我想在tsql(MSSQL2014)中获取一些数据,我使用子查询来获得一些外键数据表的总和。mssql subquery aggregate - sum wrong

的结构是这样的:

TABLE [AggregateData](
    [Id] [bigint] IDENTITY(1,1) NOT NULL, 
    [Aggregate_UUID] [uniqueidentifier] NOT NULL, 
    [DataDate] [date] NOT NULL, 
    [SizeAvailable] [bigint] NOT NULL, 
    [SizeTotal] [bigint] NOT NULL, 
    [SizeUsed] [bigint] NOT NULL, 
    [PercentageUsed] [int] NOT NULL 
) 

TABLE [Aggregate](
    [Id] [bigint] IDENTITY(1,1) NOT NULL, 
    [UUID] [uniqueidentifier] NOT NULL, 
    [Name] [nvarchar](255) NOT NULL, 
    [Cluster_UUID] [uniqueidentifier] NOT NULL, 
    [DiskTypeID] [int] NOT NULL 
) 

TABLE [DiskType](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [TypeName] [nvarchar](255) NULL 
) 

TABLE [Volume](
    [Id] [bigint] IDENTITY(1,1) NOT NULL, 
    [UUID] [uniqueidentifier] NOT NULL, 
    [Name] [nvarchar](255) NOT NULL, 
    [Aggregate_UUID] [uniqueidentifier] NOT NULL, 
    [ServiceClassID] [int] NULL, 
    [ProtocolID] [int] NOT NULL, 
    [EnvironmentID] [int] NOT NULL 
) 

TABLE [VolumeData](
    [Id] [bigint] IDENTITY(1,1) NOT NULL, 
    [Volume_UUID] [uniqueidentifier] NOT NULL, 
    [DataDate] [date] NOT NULL, 
    [SizeAvailable] [bigint] NOT NULL, 
    [SizeTotal] [bigint] NOT NULL, 
    [SizeUsed] [bigint] NOT NULL, 
    [PercentageUsed] [int] NOT NULL 
) 

现在到底我需要得到以下数据:

DataDate,DiskType,AggregateSizes(其他,使用,总计),汇总卷的大小(使用的总和,使用,在该总量的总量)

我想使用子查询,但试图只获得一个特定的聚合值(测试,更容易我检查)我在子查询中得到错误的值。

这是我试过的;

SELECT 
    AggregateData.DataDate, 
    AggregateData.SizeTotal AS AggregateSizeTotal, 
    (SELECT 
    SUM(VolumeData.SizeTotal) 
    FROM VolumeData 
    LEFT JOIN Volume 
    ON VolumeData.Volume_UUID = Volume.UUID 
    WHERE Aggregate_UUID = Volume.Aggregate_UUID 
    AND VolumeData.DataDate = AggregateData.DataDate) 
    VolumeSizeTotal 

FROM AggregateData 

WHERE AggregateData.Aggregate_UUID = 'C58D0098-D1A4-4EE9-A0E9-7DE3EEB6275C' 
ORDER BY AggregateData.DataDate 

但是,这似乎我没有得到正确的值的子查询总和。我的子查询总和的方式来高,所以我想我的where子句是不正确的(或整个设置;)...)

  • 所以,问题1.是否子查询要走的路还是应该采取不同的方式?
  • 如果(问题1 == true)我的子查询出了什么问题?

回答

1

您需要限定全部列名。我会建议使用表缩写。问题是Aggregate_UUID = v.Aggregate_UUID。第一列来自v,所以这是(基本上)没有任何操作。

想必,你要想这与外部查询相关:

SELECT ad.DataDate, ad.SizeTotal AS AggregateSizeTotal, 
     (SELECT SUM(vd.SizeTotal) 
     FROM VolumeData vd LEFT JOIN 
      Volume v 
      ON vd.Volume_UUID = v.UUID 
     WHERE ad.Aggregate_UUID = v.Aggregate_UUID AND 
       ad.DataDate = vd.DataDate 
     ) VolumeSizeTotal 
FROM AggregateData ad 
WHERE ad.Aggregate_UUID = 'C58D0098-D1A4-4EE9-A0E9-7DE3EEB6275C' 
ORDER BY ad.DataDate 
+0

是的,你是对的。这对select中的子查询看起来很不错。现在对于我需要的所有其他列,我需要在select中添加另一个子查询,因为据我所知在select中使用时只能返回1个值。这会使它使用起来有点麻烦。所以,虽然有效的我的事情,我选择使用子查询的初始方法并不理想。我将在连接中使用子查询来尝试它。似乎我需要更好的方法。 – Marc

+0

@Marc。 。 。如果您有*另一个问题涉及多个栏目,那么您应该将其作为问题而不是评论。 –

+0

你说得对。所以我会在第二部分提出另一个问题。非常感谢。 – Marc

0

为此,您可以使用JOIN,而不是相关子查询(为O(n^2)性能) -

SELECT 
    t1.DataDate, 
    t1.SizeTotal AS AggregateSizeTotal, 
    t2.total VolumeSizeTotal 
FROM AggregateData t1 left join (SELECT 
    DataDate, SUM(VolumeData.SizeTotal) total 
    FROM VolumeData 
    LEFT JOIN Volume 
    ON VolumeData.Volume_UUID = Volume.UUID 
    WHERE Aggregate_UUID = Volume.Aggregate_UUID 
    group by DataDate) t2 on t1.datadate = t2.dataDate 
WHERE t1.Aggregate_UUID = 'C58D0098-D1A4-4EE9-A0E9-7DE3EEB6275C'; 
0

展望为查询返回所需的最终结果,我会使用这样的事情:

现在到最后我需要得到以下da TA:DataDate,DiskType,AggregateSizes(其他,使用,总计),聚合卷大小(其他,总和中,在总体积的合计)

select AggregateUuid = a.uuid , DiskType = dt.TypeName , DataDate = ad.DataDate , AggregateSizeAvailable = ad.SizeAvailable , AggregateSizeUsed = ad.SizeUsed , AggregateSizeTotal = ad.SizeTotal , VolumeSizeAvailable = sum(vd.SizeAvailable) , VolumeSizeUsed = sum(vd.SizeUsed) , VolumeSizeTotal = sum(vd.SizeTotal) from [Aggregate] a inner join DiskType dt on dt.Id = a.DiskTypeId inner join AggregateData ad on ad.Aggregate_uuid = a.uuid left join Volume v on v.Aggregate_uuid = a.uuid left join VolumeData vd on vd.Volume_uuid = v.uuid and vd.DataDate = ad.DataDate where a.uuid = 'C58D0098-D1A4-4ee9-A0E9-7de3eeb6275C' group by a.uuid , dt.TypeName , ad.DataDate , ad.SizeAvailable , ad.SizeUsed , ad.SizeTotal order by a.uuid, ad.DataDate; 

测试设置

http://rextester.com/HZZHLI45077

create table DiskType(
    Id int identity(1,1) not null 
    , TypeName nvarchar(255) null 
); 
set identity_insert DiskType on; 
insert into DiskType (Id, TypeName) values 
    (1,'Type1'), (2,'Type2'); 
set identity_insert DiskType off; 

create table [Aggregate](
    Id bigint identity(1,1) not null 
    , uuid uniqueidentifier not null 
    , Name nvarchar(255) not null 
    , Cluster_uuid uniqueidentifier not null 
    , DiskTypeid int not null 
); 

insert into [Aggregate] (uuid, name, cluster_uuid, disktypeid) 
      select 'C58D0098-D1A4-4EE9-A0E9-7DE3EEB6275C', 'ex', newid(), 1; 

create table AggregateData(
    Id bigint identity(1,1) not null 
    , Aggregate_uuid uniqueidentifier not null 
    , DataDate date not null 
    , SizeAvailable bigint not null 
    , SizeTotal bigint not null 
    , SizeUsed bigint not null 
    , PercentageUsed int not null 
); 

insert into AggregateData 
      select 'C58D0098-D1A4-4EE9-A0E9-7DE3EEB6275C', '20170101', 12,100,87,87 
    union all select 'C58D0098-D1A4-4EE9-A0E9-7DE3EEB6275C', '20170102', 9,100,90,90 
    union all select 'C58D0098-D1A4-4EE9-A0E9-7DE3EEB6275C', '20170103', 6,100,93,93; 

create table Volume(
    Id bigint identity(1,1) not null 
    , uuid uniqueidentifier not null 
    , Name nvarchar(255) not null 
    , Aggregate_uuid uniqueidentifier not null 
    , ServiceClassid int null 
    , Protocolid int not null 
    , Environmentid int not null 
); 
insert into Volume 
      select '00000000-0000-0000-0000-000000000001', 'v1' 
       , 'C58D0098-D1A4-4EE9-A0E9-7DE3EEB6275C', null, 1, 1 
    union all select '00000000-0000-0000-0000-000000000002', 'v2' 
       , 'C58D0098-D1A4-4EE9-A0E9-7DE3EEB6275C', null, 1, 1 
    union all select '00000000-0000-0000-0000-000000000003', 'v3' 
       , 'C58D0098-D1A4-4EE9-A0E9-7DE3EEB6275C', null, 1, 1; 

create table VolumeData(
    Id bigint identity(1,1) not null 
    , Volume_uuid uniqueidentifier not null 
    , DataDate date not null 
    , SizeAvailable bigint not null 
    , SizeTotal bigint not null 
    , SizeUsed bigint not null 
    , PercentageUsed int not null 
); 

insert into VolumeData 
      select '00000000-0000-0000-0000-000000000001', '20170101', 4,33,29,88 
    union all select '00000000-0000-0000-0000-000000000002', '20170101', 4,33,29,88 
    union all select '00000000-0000-0000-0000-000000000003', '20170101', 4,34,29,87 
    union all select '00000000-0000-0000-0000-000000000001', '20170102', 3,33,30,91 
    union all select '00000000-0000-0000-0000-000000000002', '20170102', 3,33,30,91 
    union all select '00000000-0000-0000-0000-000000000003', '20170102', 3,34,30,90 
    union all select '00000000-0000-0000-0000-000000000001', '20170103', 2,33,31,94 
    union all select '00000000-0000-0000-0000-000000000002', '20170103', 2,33,31,94 
    union all select '00000000-0000-0000-0000-000000000003', '20170103', 2,34,31,93 

go 
/* -------------------------------------------------------- */ 

select 
     AggregateUuid   = a.uuid 
    , DiskType    = dt.TypeName 
    , DataDate    = convert(varchar(10),ad.DataDate,121) 
    , AggregateSizeAvailable = ad.SizeAvailable 
    , AggregateSizeUsed  = ad.SizeUsed 
    , AggregateSizeTotal  = ad.SizeTotal 
    , VolumeSizeAvailable = sum(vd.SizeAvailable) 
    , VolumeSizeUsed   = sum(vd.SizeUsed) 
    , VolumeSizeTotal  = sum(vd.SizeTotal) 
    from [Aggregate] a 
     inner join DiskType  dt on dt.Id    = a.DiskTypeId 
     inner join AggregateData ad on ad.Aggregate_uuid = a.uuid 
     left join Volume   v on v.Aggregate_uuid = a.uuid 
     left join VolumeData  vd on vd.Volume_uuid = v.uuid 
           and vd.DataDate  = ad.DataDate 
    where a.uuid = 'C58D0098-D1A4-4ee9-A0E9-7de3eeb6275C' 
    group by 
     a.uuid 
    , dt.TypeName 
    , ad.DataDate 
    , ad.SizeAvailable 
    , ad.SizeUsed 
    , ad.SizeTotal 
    order by a.uuid, ad.DataDate; 

结果:

+--------------------------------------+----------+------------+------------------------+-------------------+--------------------+---------------------+----------------+-----------------+ 
|   AggregateUuid    | DiskType | DataDate | AggregateSizeAvailable | AggregateSizeUsed | AggregateSizeTotal | VolumeSizeAvailable | VolumeSizeUsed | VolumeSizeTotal | 
+--------------------------------------+----------+------------+------------------------+-------------------+--------------------+---------------------+----------------+-----------------+ 
| c58d0098-d1a4-4ee9-a0e9-7de3eeb6275c | Type1 | 2017-01-01 |      12 |    87 |    100 |     12 |    87 |    100 | 
| c58d0098-d1a4-4ee9-a0e9-7de3eeb6275c | Type1 | 2017-01-02 |      9 |    90 |    100 |     9 |    90 |    100 | 
| c58d0098-d1a4-4ee9-a0e9-7de3eeb6275c | Type1 | 2017-01-03 |      6 |    93 |    100 |     6 |    93 |    100 | 
+--------------------------------------+----------+------------+------------------------+-------------------+--------------------+---------------------+----------------+-----------------+ 
+0

这将给我每卷一个条目,但我需要每个聚合1条目,卷大小列是该特定聚合中所有卷的总和。对不起,我最初的帖子不清楚。 – Marc

+0

@Marc更新后的答案会删除卷名,这应该会返回您正在查找的内容。 – SqlZim

+0

由于我们正在总结所有体积数据,因此仍然得到了多个具有相同体积的聚合体的行,因为没有按“体积”分组。 – Marc