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