SQL to LINQ with Case .当按顺序
本文关键字:顺序 Case with to LINQ SQL | 更新日期: 2023-09-27 18:31:23
我有一个SQL查询,我想将其转换为LINQ查询,但不确定如何进行。我有两个实体Product
和Price
.Price
通过ProductId
链接到Product
。查询根据请求Product
的数量获取产品的最佳价格。
例如:如果客户想要购买 10 件产品,则产品的价格可能为 5 美元/单位。但是,如果客户想要购买 100 个单位的产品,那么成本可能是 3 美元/单位。此查询将根据请求的数量获得最佳单价。WHERE 子句确保选择正确的产品,如果日期已过期,则排除任何价格。CASE 语句对价格进行排序,以便只要达到请求的数量,就会首先显示最佳价格。
Price Table
--------------------------
Id ProductId Quantity Price BeginDate EndDate
=========================================================================
1 1234 10 $5 1/1/2016 2/1/2016
2 1234 100 $3 1/1/2016 2/1/2016
3 1234 100 $1 1/1/2016 1/9/2016
4 1234 500 $2 1/1/2016 2/1/2016
SELECT TOP 1
Product.Id,
Product.Name,
Prices.Price
FROM Products INNER JOIN Prices ON Products.Id = Prices.ProductId
WHERE Product.Id = @ProductId
AND ((Price.BeginDate IS NULL OR Price.BeginDate < GETDATE()) AND (Price.EndDate IS NULL OR Price.EndDate > GETDATE()))
ORDER BY
CASE WHEN Price.Quantity <= @RequestedQuantity THEN Price.Quantity
ELSE -Price.Quantity
END
在 LINQ 中让我感到困惑的查询部分..
- 如何筛选出价格日期已过期的价格(例如 Id = 3)。
- 如何使用案例语句对集合进行排序。
一旦这些就位,我就可以使用 FirstOrDefault
选择顶部结果
尝试使用 let
关键字来定义列并对其进行排序。我没有测试它,我不确定它会像你期望的那样工作。对于示例,请确保在其上定义了所有实体和属性:
var query = from product in Products
join price in Prices on product.Id equals price.ProductId
let priceOrder = price.Quantity <= requestValue ? price.Quantity : -price.Quantity
where ((price.BeginDate == null || Price.BeginDate < DateTime.Now) && (Price.EndDate == null || Price.EndDate > DateTime.Now))
orderby priceOrder
select { product.Id, product.Name, price.Price };
var result = query.FirstOrDefault();
如果您使用的是实体框架
SELECT TOP 1
Product.Id,
Product.Name,
Prices.Price
FROM Products INNER JOIN Prices ON Products.Id = Prices.ProductId
WHERE Product.Id = @ProductId
AND ((Price.BeginDate IS NULL OR Price.BeginDate < GETDATE()) AND (Price.EndDate IS NULL OR Price.EndDate > GETDATE()))
ORDER BY
CASE WHEN Price.Quantity <= @RequestedQuantity THEN Price.Quantity
ELSE -Price.Quantity
END
应该看起来像
var SelectedProduct = ObjectYourDatabaseIsLabeledAs.Products
.FirstOrDefault(p => p.Id == ProductId) // Gets matching Ids
或
var SelectedProduct = ObjectYourDatabaseIsLabeledAs.Products.Find(ProductId)
然后得到合适的价格
var SelectedPrice = SelectedProduct?.Prices
.OrderByDesc(o => o.Quantity) // Sets the highest number at the top of the IEnum
.FirstOrDefault(p => // Take the first/default one where...
p.EndDate >= DateTime.Today &&
p.StartDate <= DateTime.Today && // Gets All With Valid Prices
p.Quantity <= RequestedQuantity) // Removes all the high quantities that you don't want
这几乎是一对一的翻译。
.SQL
SELECT TOP 1 Product.Id, Product.Name, Prices.Price
FROM Products
INNER JOIN Prices ON Products.Id = Prices.ProductId
WHERE Product.Id = @ProductId
AND (Price.BeginDate IS NULL OR Price.BeginDate < GETDATE())
AND (Price.EndDate IS NULL OR Price.EndDate > GETDATE())
ORDER BY CASE WHEN Price.Quantity <= @RequestedQuantity THEN Price.Quantity ELSE -Price.Quantity END
林克
var productId = ...;
var requestedQuantity = ...;
var date = DateTime.Today;
var query =
(from product in db.Products
join price in db.Prices on product.Id equals price.ProductId
where product.Id == productId
&& (price.BeginDate == null || price.BeginDate < date)
&& (price.EndDate == null || price.EndDate > date)
orderby price.Quantity <= requestedQuantity ? price.Quantity : -price.Quantity
select new { product.Id, product.Name, price.Price }
).Take(1);
var result = query.FirstOrDefault();
唯一的区别是select
排在最后,CASE WHEN condition THEN a ELSE b END
映射到condition ? a : b
,TOP n
变得.Take(n)
.
实际上这里不需要Take(1)
,我将其包含在内只是为了进行比较,以防您需要TOP 10
例如。