带有Case的SQL到LINQ ..在按顺序时

时间:2016-01-21 16:34:38

标签: c# linq

我有一个SQL查询,我想转换成LINQ查询,但我不知道如何继续。我有两个实体ProductPricePriceProduct ProductId相关联。该查询根据所请求的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中感到困惑..

  1. 如何过滤出价格日期已过期的价格(例如Id = 3)。
  2. 如何使用案例陈述订购集合。
  3. 一旦这些到位,我就可以使用FirstOrDefault

    选择最高结果

3 个答案:

答案 0 :(得分:3)

尝试使用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();

答案 1 :(得分:2)

如果您使用的是实体框架

DhtListener listener = new DhtListener(new IPEndPoint(IPAddress.Parse("192.168.2.3"), 10000));

应该看起来像

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)

答案 2 :(得分:1)

这是一对一的翻译。

<强> 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

<强> LINQ

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 : bTOP n变为.Take(n)

实际上这里不需要Take(1),我只是为了比较而将其包含在内,以备你需要TOP 10时使用。