T-SQL 版本的查詢
讓我們用一些資料設定一個簡單的表:
DROP TABLE IF EXISTS #OrdersTable
CREATE TABLE #OrdersTable
(
Id int,
Custid int
);
INSERT INTO #OrdersTable (Id, Custid) VALUES (1, 71);
INSERT INTO #OrdersTable (Id, Custid) VALUES (2, 71);
INSERT INTO #OrdersTable (Id, Custid) VALUES (3, 71);
INSERT INTO #OrdersTable (Id, Custid) VALUES (4, 72);
INSERT INTO #OrdersTable (Id, Custid) VALUES (5, 72);
INSERT INTO #OrdersTable (Id, Custid) VALUES (6, 72);
INSERT INTO #OrdersTable (Id, Custid) VALUES (7, 73);
INSERT INTO #OrdersTable (Id, Custid) VALUES (8, 74);
INSERT INTO #OrdersTable (Id, Custid) VALUES (9, 74);
在這種情況下,客戶 71 和 72 各有 3 個訂單。客戶 73 有 1 個訂單。客戶 74 有 2 個訂單。
假設我們想知道訂單數量最多的客戶。
以下查詢:
SELECT TOP (1) WITH TIES Custid
FROM #OrdersTable
GROUP BY Custid
ORDER BY COUNT(*) DESC;
結果如下:
Custid
-----------
71
72
(2 rows affected)
簡單轉換為 EF Core
鑒于以下類:
public class Order
{
public int Id { get; set; }
public int Custid { get; set; }
}
以及以下資料:
var OrdersTable = new List<Order>()
{
new Order(){ Id = 1, Custid = 71},
new Order(){ Id = 2, Custid = 71},
new Order(){ Id = 3, Custid = 71},
new Order(){ Id = 4, Custid = 72},
new Order(){ Id = 5, Custid = 72},
new Order(){ Id = 6, Custid = 72},
new Order(){ Id = 7, Custid = 73},
new Order(){ Id = 8, Custid = 74},
new Order(){ Id = 9, Custid = 74},
};
這是查詢到 EF Core 的簡單轉換:
var n = OrdersTable.GroupBy(order => order.Custid).Select(grouping => grouping.Count()).Max();
var custids = OrdersTable.GroupBy(order => order.Custid).Where(grouping => grouping.Count() == n).Select(grouping => grouping.Key);
使用以下內容顯示資料:
foreach (var custid in custids)
Console.WriteLine(custid);
我們得到:
71
72
題
讓我們并排放置 T-SQL 和 EF Core 版本。T-SQL:
SELECT TOP (1) WITH TIES Custid
FROM #OrdersTable
GROUP BY Custid
ORDER BY COUNT(*) DESC;
英孚核心:
var n = OrdersTable.GroupBy(order => order.Custid).Select(grouping => grouping.Count()).Max();
var custids = OrdersTable.GroupBy(order => order.Custid).Where(grouping => grouping.Count() == n).Select(grouping => grouping.Key);
我的問題是,是否有更有效的方法在 EF Core 中實作此查詢?
完整程式
演示上述查詢的完整 C# 控制臺程式:
using System;
using System.Collections.Generic;
using System.Linq;
namespace EfCoreTop1Ties
{
public class Order
{
public int Id { get; set; }
public int Custid { get; set; }
}
internal class Program
{
static void Main(string[] args)
{
var OrdersTable = new List<Order>()
{
new Order(){ Id = 1, Custid = 71},
new Order(){ Id = 2, Custid = 71},
new Order(){ Id = 3, Custid = 71},
new Order(){ Id = 4, Custid = 72},
new Order(){ Id = 5, Custid = 72},
new Order(){ Id = 6, Custid = 72},
new Order(){ Id = 7, Custid = 73},
new Order(){ Id = 8, Custid = 74},
new Order(){ Id = 9, Custid = 74},
};
var n = OrdersTable.GroupBy(order => order.Custid).Select(grouping => grouping.Count()).Max();
var custids = OrdersTable.GroupBy(order => order.Custid).Where(grouping => grouping.Count() == n).Select(grouping => grouping.Key);
foreach (var custid in custids)
Console.WriteLine(custid);
}
}
}
uj5u.com熱心網友回復:
您應該能夠通過一個查詢來做到這一點:
var n = OrdersTable
.GroupBy(order => order.Custid)
.Select(grouping => new { CustomerId = grouping.Key, OrderCount = grouping.Count() })
.OrderByDescending(g => g.OrderCount)
.ToList();
var maxCount = n.First().OrderCount;
var custIds = n.Where(g => g.OrderCount == maxCount)
.Select(g => g.CustomerId)
.ToList();
在 OrdersTable 是 DbContext DBSet 的情況下,這將導致對資料庫的 1 次查詢。檢查與該計數匹配的回傳專案是在記憶體中根據結果進行的,無需回傳。
如果您正在處理一個特別大的資料集,您可以考慮一些合理的假設,例如,如果有數千名客戶,那么 100 名或 1000 名是否可能會“系結”最大數量的訂單。
var n = OrdersTable
.GroupBy(order => order.Custid)
.Select(grouping => new { CustomerId = grouping.Key, OrderCount = grouping.Count() })
.OrderByDescending(g => g.OrderCount)
.Take(100)
.ToList();
if (n.All(g => g.OrderCount == n.First().OrderCount)
// Redo query with larger threshold.
如果所有回傳的行碰巧具有相同的訂單計數,它將再次運行查詢。您可能希望以不同的方式處理這種情況,例如當所有客戶都有 0 個訂單時。(如果您有選擇要比較的客戶的標準,例如每個城市/州等)
要覆寫一個非常大的資料表,另一種選擇就是查詢最大計數,前提是您的物體配置了導航屬性,以便您的 Customer 物體可以與它的 Orders 集合相關聯:
var maxOrderCount = dbContext.Customers
.OrderByDescending(x => x.Orders.Count)
.Select(x => x.Orders.Count)
.First();
var customers = dbContext.Customers
.Where(x => x.Orders.Count == maxOrderCount)
.ToList();
如果您只想要客戶 ID .Select(x => x.CustomerId),ToList()則在之前添加。它運行兩個查詢,但它們相當簡單,只回傳所需的資料,而不是潛在的所有客戶 ID/資料。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/359179.html
上一篇:如何在物體框架的遷移中在“半”多對多上顯式設定索引或外鍵的名稱?
下一篇:如何從可列舉轉換為特定模型
