poniedziałek, 4 lutego 2013

LINQ - użycie GroupJoin


Zadanie jest następujące:
Na podstawie poniższego schematu (baza AdventureWorksLT) wyznaczyć wartość zamówienia. Dodać kolumny z id klienta i zamówienia (bez uwzględnienia podatku, obniżek itp).





W zapytaniu wykorzystamy GroupJoin.

Zapytanie to zapiszemy w dwóch postaciach LINQ2SQ: metodowej oraz SQLo podobnej:

Code:
            var res = context.SalesOrderHeaders.
                              GroupJoin(context.SalesOrderDetails, header => header.SalesOrderID,
                                        detail => detail.SalesOrderID,
                                        (header, details) => new
                                                                 {
                                                                     CustomerId = header.CustomerID,
                                                                     OrderId = header.SalesOrderID,
                                                                     TotalPrice = details.Sum(x => x.UnitPrice * x.OrderQty)
                                                                 });


  Code:
             var res2 = from a in context.SalesOrderDetails
                       group a by a.SalesOrderID
                       into g
                       join b in context.SalesOrderHeaders on g.Key equals b.SalesOrderID
                       select new
                                  {
                                      CustomerId = b.CustomerID,
                                      OrderId = b.SalesOrderID,
                                      TotalPrice = g.Sum(x => x.UnitPrice*x.OrderQty)
                                  };





Obydwa zapytania zwracają te same rezultaty i są poprawne pod względem składni LINQ. Ciekawszym aspektem może być zapytanie SQL generowane przez te dwa zapytania. Dla pierwszego zapytania zostanie wygenerowany następujący kod SQL:
SELECT [Extent1].[SalesOrderID] AS [SalesOrderID], [Extent1].[CustomerID] AS [CustomerID],
(
SELECT
  
SUM([Filter1].[A1]) AS [A1]
  
FROM ( SELECT
      
[Extent2].[UnitPrice] *  CAST( [Extent2].[OrderQty] AS DECIMAL(19,0)) AS [A1]
      
FROM [SalesLT].[SalesOrderDetail] AS [Extent2]
      
WHERE [Extent1].[SalesOrderID] = [Extent2].[SalesOrderID]
  
)  AS [Filter1]) AS [C1]FROM [SalesLT].[SalesOrderHeader] AS [Extent1]



Drugie z zapytań wygenerowało następującego SQLa:


SELECT [Distinct1].[SalesOrderID] AS [SalesOrderID], [Extent2].[CustomerID] AS [CustomerID], [Extent2].[SalesOrderID] AS [SalesOrderID1],
(
SELECT
  
SUM([Filter1].[A1]) AS [A1]
  
FROM ( SELECT
      
[Extent3].[UnitPrice] *  CAST( [Extent3].[OrderQty] AS DECIMAL(19,0)) AS [A1]
      
FROM [SalesLT].[SalesOrderDetail] AS [Extent3]
      
WHERE [Distinct1].[SalesOrderID] = [Extent3].[SalesOrderID]
  
)  AS [Filter1]) AS [C1]FROM   (SELECT DISTINCT
  
[Extent1].[SalesOrderID] AS [SalesOrderID]
  
FROM [SalesLT].[SalesOrderDetail] AS [Extent1] ) AS [Distinct1]INNER JOIN [SalesLT].[SalesOrderHeader] AS [Extent2] ON [Distinct1].[SalesOrderID] = [Extent2].[SalesOrderID]


Rozwiązania podobne w składni a wynik zapytania SQL różny dla każdego z dwóch rozwiązań. Jeżeli weźmiemy pod uwagę wydajność to w przypadku pierwszego zapytania będzie ona większa. Jeżeli przyszłoby mi napisać samemu to zapytanie skorzystałbym z następującego zapytania:

SELECT header.SalesOrderID, header.CustomerID, details.TotalPriceFROM SalesLT.SalesOrderHeader header JOIN
  
(SELECT SUM(details.UnitPrice * details.OrderQty) AS TotalPrice, details.SalesOrderID
  
FROM SalesLT.SalesOrderDetail details
  
GROUP BY details.SalesOrderID) AS details ON header.SalesOrderID = details.SalesOrderID

Brak komentarzy:

Prześlij komentarz