目标:获取所有产品、最新季度的总销售额、上一季度的总销售额以及所有季度的平均销售额
QuarterlyReport {
Id
EndDate
ProductId
}
SalesRecord {
QuarterlyReportId
SalesAmount
}
Product {
Id
}
到目前为止我们所拥有的:
获取所有 QuarterlyReports 以及所有关联记录的 SalesAmount 的总和,使用它来查询我们的其余数据
With QRU as (
SELECT QuarterlyReport.ProductId as productId, QuarterlyReport.EndDate as
reportEndDate, SUM(SalesRecord.SalesAmount) as QuarterlyTotalSales
FROM table_QuarterlyReports as QuarterlyReport LEFT JOIN table_SalesRecords
as SalesRecord on QuarterlyReport.Id = SalesRecord.QuarterlyReportId
Group BY QuarterlyReport.ProductId, QuarterlyReport.EndDate
)
Select DISTINCT product.*,
(select avg(QuarterlyTotalSales) from QRU where QRU.productId = product.Id) as averageSales,
(select TOP 1 QuarterlyTotalSales from QRU where QRU.productId = product.Id
ORDER BY reportEndDate DESC) as ThisQuarterSales,
(select QuarterlyTotalSales from QRU where QRU.productId = product.Id ORDER
BY reportEndDate DESC OFFSET 1 rows fetch next 1 rows only) as LastQuarterSales
From table_Products as product
这是模拟表:
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[table_Products](
[Location] [int] NOT NULL,
[Id] [int] IDENTITY(1,1) NOT NULL)
GO
CREATE TABLE [dbo].[table_QuarterlyReports](
[EndDate] [datetime] NOT NULL,
[ProductId] [int] NOT NULL,
[Id] [int] IDENTITY(1,1) NOT NULL)
GO
CREATE TABLE [dbo].[table_SalesRecords](
[QuarterlyReportId] [int] NOT NULL,
[SalesAmount] [bigint] NOT NULL,
[Id] [int] IDENTITY(1,1) NOT NULL)
GO
INSERT INTO [dbo].[table_Products] VALUES (1);
INSERT INTO [dbo].[table_Products] VALUES (2);
INSERT INTO [dbo].[table_Products] VALUES (3);
INSERT INTO [dbo].[table_QuarterlyReports] VALUES ('20170502 12:00:00 AM', 1)
INSERT INTO [dbo].[table_QuarterlyReports] VALUES ('20170502 12:00:00 AM', 2)
INSERT INTO [dbo].[table_QuarterlyReports] VALUES ('20170502 12:00:00 AM', 3)
INSERT INTO [dbo].[table_QuarterlyReports] VALUES ('20170402 12:00:00 AM', 1)
INSERT INTO [dbo].[table_QuarterlyReports] VALUES ('20170402 12:00:00 AM', 2)
INSERT INTO [dbo].[table_QuarterlyReports] VALUES ('20170402 12:00:00 AM', 3)
INSERT INTO [dbo].[table_SalesRecords] VALUES (1, 1000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (1, 2000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (2, 7000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (2, 1000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (3, 2000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (3, 3000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (4, 5000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (4, 4000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (5, 4000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (5, 2000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (6, 4000);
INSERT INTO [dbo].[table_SalesRecords] VALUES (6, 3000);
这是可行的,尽管我们希望它全部包含在一个查询中。此外,我们正在尝试将此查询转换为 Entity Framework LINQ to Entities。
最佳答案
可以通过联接来完成,但在 EF 中,您最好定义和使用导航属性。
以下是具有集合导航属性的示例模型:
[Table("table_Products")]
public class Product
{
public int Id { get; set; }
public int Location { get; set; }
// Navigation properties
[ForeignKey("ProductId")]
public ICollection<QuarterlyReport> QuarterlyReports { get; set; }
}
[Table("table_QuarterlyReports")]
public class QuarterlyReport
{
public int Id { get; set; }
public DateTime EndDate { get; set; }
public int ProductId { get; set; }
// Navigation properties
[ForeignKey("QuarterlyReportId")]
public ICollection<SalesRecord> SalesRecords { get; set; }
}
[Table("table_SalesRecords")]
public class SalesRecord
{
public int Id { get; set; }
public int QuarterlyReportId { get; set; }
public long SalesAmount { get; set; }
}
那么等效的 LINQ to Entities 查询可能如下所示:
var query =
from p in db.Products
let sales =
from qr in p.QuarterlyReports // inner join
from sr in qr.SalesRecords.DefaultIfEmpty() // left join
group sr by qr.EndDate into srg
select new
{
Date = srg.Key,
Amount = (from sr in srg select (long?)sr.SalesAmount).Sum()
}
select new
{
p.Id,
p.Location,
AverageSales = (from s in sales select s.Amount)
.Average(),
ThisQuarterSales = (from s in sales orderby s.Date descending select s.Amount)
.FirstOrDefault(),
LastQuarterSales = (from s in sales orderby s.Date descending select s.Amount)
.Skip(1).FirstOrDefault(),
};
关于SQL 通过/左连接按组获取最大 n 的所有行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43787290/