2017-08-02 91 views
0

我试图将下面的Oracle Sql查询转换为linq,但没有取得太大的成功。我不知道如何处理AND ShipSeq = i.ShipSeq(+),我知道这是在Oracle中的LEFT OUTER JOIN。我在LinqPad中测试下面的Linq查询,在那里我没有得到任何语法错误,但是它在执行查询时出错。有任何想法吗?将具有左外部联接的Oracle SQL查询转换为Linq

的Oracle SQL查询

SELECT * 
FROM CustomerShip, 
    (SELECT DISTINCT b.ShipSeq AS shipSeq 
    FROM Orders a, 
      CustomerShip b 
    WHERE a.OrderId IN (SELECT OrderId 
          FROM Orders 
          WHERE CustomerId = @CustomerId 
          AND OrderType <> 'A') 
    AND b.CustomerId = @CustomerId 
    AND b.ShipSeq = a.CustShip 
    AND OrderStatus <> 'C' 
    GROUP BY b.ShipSeq) i 
WHERE CustomerId = @CustomerId 
AND (Address NOT LIKE '%RETAIL%STORE%') 
AND ShipSeq = i.ShipSeq(+) 
ORDER BY ShipTo DESC, OrderDate DESC; 

LINQ查询

var query = from s in CustomerShip 
      join m in Orders on s.ShipTo equals m.ShipTo into temp 
      from x in temp.DefaultIfEmpty() 
      where (from o in Orders 
        from c in CustomerShip 
        where (from x in CustomerOrders 
          where x.CustomerId == customerId 
          && !x.OrderType.Equals("A") 
          select x.OrderId).Contains(o.OrderId) 
        && c.CustomerId == customerId 
        && c.ShipTo == o.ShipTo 
        && !o.OrderStatus.Equals("C") 
        select c.ShipTo).Distinct().Contains(s.ShipTo) 
      && s.CustomerId == customerId 
      && !s.Address.Contains("RETAIL") 
      && !s.Address.Contains("STORE") 
      orderby s.ShipTo descending, s.OrderDate descending 
      select s; 
+0

这可能有助于(https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b)有一个部分上加入 –

回答

0

我认为直译是这样的:

var iQuerySub = from o in Orders where o.CustomerId == pCustomerId && o.OrderType != "A" select o.OrderId; 

var iQuery = (from a in Orders 
       from b in CustomerShip 
       where iQuerySub.Contains(a.OrderId) && 
       b.CustomerId == pCustomerId && 
       b.ShipSeq == a.CustShip && 
       a.OrderStatus != "C" 
       group b by b.ShipSeq into bg 
       select new { shipSeq = bg.Key }).Distinct(); 

var ans = from s in CustomerShip 
      where s.CustomerId == pCustomerId && 
      (!s.Address.Contains("RETAIL") || !s.Address.Contains("STORE") || s.Address.IndexOf("RETAIL") > s.Address.IndexOf("STORE")) 
      join i in iQuery on s.ShipSeq equals i.shipSeq into ij 
      from i in ij.DefaultIfEmpty() 
      orderby s.ShipTo, s.OrderDate descending 
      select new { s, shipSeq = (i != null ? i.shipSeq : (int?)null) }; 

然而无论是SQL和LINQ似乎ineffi cient给我,但没有领域知识,这是所有我可以优化:

var iQuery2 = (from b in CustomerShip 
       where b.CustomerId == pCustomerId && 
       Orders.Any(a => a.CustomerId == pCustomerId && a.OrderType != "A" && a.OrderStatus != "C" && b.ShipSeq == a.CustShip) 
       select new { shipSeq = b.ShipSeq }).Distinct(); 

var ans2 = from s in CustomerShip 
      where s.CustomerId == pCustomerId && 
      (!s.Address.Contains("RETAIL") || !s.Address.Contains("STORE") || s.Address.IndexOf("RETAIL") > s.Address.IndexOf("STORE")) 
      join i in iQuery2 on s.ShipSeq equals i.shipSeq into ij 
      from i in ij.DefaultIfEmpty() 
      orderby s.ShipTo, s.OrderDate descending 
      select new { s, shipSeq = (i != null ? i.shipSeq : (int?)null) }; 
+0

谢谢你的努力。您的答案几乎适用于我,但在'iQuery'查询中,我在LinqPad中测试时遇到错误:'不是GROUP BY表达式' – PixelPaul

+0

我想我已经确定了这个问题,但不知道如何更正。当我查看生成的SQL时,它有一个“GROUP BY b.ShipSeq”,但查询的第一行是'SELECT b.ShipSeq,c.OrderId'。不知道为什么'c.OrderId'在select语句中? – PixelPaul

+0

这可能是LINQ为了处理需要'OrderId'的'where iQuerySub.Contains'而如何实现'iQuerySub'。我在一个匿名对象模型的LINQPad中运行了这个,但是显然我没有真正的数据库甚至模式,所以我不确定我的模型是否正确 - 在翻译时我不得不猜测哪些表的某些列属于没有方案或明确的别名表达。 – NetMage