Эффективность запросов Linq с использованием Entity Framework - PullRequest
0 голосов
/ 01 октября 2018

Мне нужно переписать огромный запрос SQL, который получает данные из примерно 10 таблиц, используя Entity Framework и Linq .Короче говоря, запрос получает список продуктов из основной таблицы, а затем извлекает другую информацию, такую ​​как количество загрузок, количество продаж, автор и т. Д., Из других таблиц для этих продуктов.

Я решил разбить его на части, чтобы другим было легко понять и отредактировать.

Сначала я получаю список продуктов.Затем я получаю данные списка для других столбцов и объединяю все вместе на последнем шаге.

 var mainTableQuery = from p in context.mains
                      select new
                      {
                         p.ProductID,
                         p.title,
                          p.department_id,
                         p.TotalInStock                                        
                       };
 //Getting the top author by priority for every product ID
 var authorLinkQuery= from authorLink in context.AuthorLinks
                      group authorLink by authorLink.ProductID
                         into groups
                      select groups.OrderBy(p=>p.Priority).FirstOrDefault();

 // Link productIDs with primary author names
 var authorsFinalQuery = from author in context.Authors
                         join authorLink in authorLinkQuery
                         on author.AuthorID equals authorLink.AuthorID
                         select new
                         {
                             authorLink.ProductID,
                             Name = (String.IsNullOrEmpty(author.Company) ? author.FirstName + " " + author.LastName : author.Company)
                         };
 var finalQuery = from main in mainTableQuery
                             join author in authorsFinalQuery
                             on main.ProductID equals author.ProductID                                 
                             select new
                             {
                                 main,
                                 author.Name
                             };

Этот последний запрос получает правильные данные, но он занимает около 30 с.Исходный запрос SQL-сервера занял всего 6 секунд.Проблема в том, что запрос SQL-сервера, который генерируется структурой сущностей, очень неэффективен.Есть ли способ оптимизировать это?

РЕДАКТИРОВАТЬ: полная хранимая процедура, которую я пытаюсь заменить:

CREATE PROCEDURE [dbo].[usp_AllProducts] (@ProgramAreaID int,
@CustomDateStart datetime,
@CustomDateEnd datetime,
@ShowNLA nvarchar(50))
AS
BEGIN 
  SET NOCOUNT ON;
  IF @ProgramAreaID = 1000
  BEGIN
    SELECT TOP (100) PERCENT
      BaseInventory.ProductID,
      BaseInventory.ReferenceNumber,
      BaseInventory.Title,
      BaseInventory.StoredBy,
      BaseInventory.TotalInStock,
      BaseInventory.StockAtEDC,
      BaseInventory.Cost,
      BaseInventory.RetailPrice,
      BaseInventory.PubDate,
      BaseInventory.DepartmentCode,
      vwAuthor.PrimaryAuthor,
      ISNULL(Sales30Days.QuantitySold, 0) AS Last30Days,
      ISNULL(SalesPastYear.QuantitySold, 0) AS Last365Days,
      ISNULL(CustomRangeSales.QuantitySold, 0) AS CustomRange,
      ISNULL(SalesPastYear.ZeroStock, '12/31/9999') AS ZeroStock,
      ISNULL(SalesPastYear.ZeroStockFullDate, CONVERT(datetime, '12/31/9999', 102)) AS ZeroStockFullDate,
      BaseInventory.FullPubDate,
      BaseInventory.ProgramArea,
      BaseInventory.Spaces,
      BaseInventory.DigitalFileExists,
      BaseInventory.DownloadCount,
      BaseInventory.DownloadCountCustom,
      ISNULL(SalesPastYear.SpacesSold, 0.000) AS SpacesSold,
      BaseInventory.DateReceived,
      BaseInventory.ProductWeight,
      BaseInventory.NumberOfPages,
      BaseInventory.DigitalFileCount,
      BaseInventory.ActiveDigitalFileCount
    FROM (SELECT TOP (100) PERCENT
      m.ProductWeight,
      m.ProductID,
      m.reference_number AS ReferenceNumber,
      m.title AS Title,
      MAX(sb.StoredBy) AS StoredBy,
      m.TotalInStock,
      m.edc_copies AS StockAtEDC,
      m.pub_cost AS Cost,
      m.RetailPrice,
      m.pub_date AS PubDate,
      d.department_code AS DepartmentCode,
      m.department_id AS DepartmentId,
      dg.department_group AS ProgramArea,
      m.FullPubDate,
      ISNULL(Boxes.Spaces, CASE
        WHEN sb.StoredBy = 'WWW' THEN 0
        ELSE 1
      END) AS Spaces,
      CASE
        WHEN ISNULL(dm.FileID, 0) = 0 THEN 'N/A'
        ELSE 'Active'
      END AS DigitalFileExists,
      ISNULL(DLs.DownloadCount, 0) AS DownloadCount,
      ISNULL(DLsCustom.DownloadCountCustom, 0) AS DownloadCountCustom,
      MAX(history.DateReceived) AS DateReceived,
      ISNULL(m.number_of_pages, 'N/A') AS NumberOfPages,
      (SELECT
        COUNT(*)
      FROM tblDigitalMedia tD
      WHERE tD.ProductID = m.ProductID)
      AS DigitalFileCount,
      (SELECT
        COUNT(*)
      FROM tblDigitalMedia tD
      WHERE tD.ProductID = m.ProductID
      AND tD.Active = 1)
      AS ActiveDigitalFileCount
    FROM dbo.main m
    INNER JOIN dbo.departments d
      ON m.department_id = d.department_id
    INNER JOIN dbo.department_groups dg
      ON d.department_group_id = dg.department_group_id

    /* InventoryTemp should be called InventoryByLocation */
    LEFT OUTER JOIN (SELECT
      m1.ProductID,
      SUM(ISNULL(it.NumberOfBoxes, 0)) + 1 AS Spaces
    FROM dbo.main AS m1
    INNER JOIN dbo.InventoryTemp AS it
      ON m1.ProductID = it.ProductID
    GROUP BY m1.ProductID) AS Boxes
      ON m.ProductID = Boxes.ProductID

    /* JobsTemp should be called JobHistory */
    LEFT OUTER JOIN dbo.JobsTemp history
      ON m.ProductID = history.ProductID

    LEFT OUTER JOIN (
    /* If dates are null then fetch for previous year. */
    SELECT TOP (100) PERCENT
      dm1.ProductID,
      COUNT(dl1.TimeStamp) AS DownloadCountCustom
    FROM dbo.tblDigitalMedia AS dm1
    LEFT OUTER JOIN dbo.tblDigitalMediaDownloads dl1
      ON dm1.FileID = dl1.FileID
    WHERE ((@CustomDateStart IS NOT NULL)
    AND (dl1.TimeStamp >= @CustomDateStart)
    AND (dl1.TimeStamp <= @CustomDateEnd))
    OR ((@CustomDateStart IS NULL)
    AND (dl1.TimeStamp BETWEEN DATEADD(D, -365, GETDATE()) AND GETDATE()))
    GROUP BY dm1.ProductID) AS DLsCustom
      ON m.ProductID = DLsCustom.ProductID
    LEFT OUTER JOIN (
    /* If dates are null then fetch for previous year. */
    SELECT TOP (100) PERCENT
      dm2.ProductID,
      COUNT(dl2.TimeStamp) AS DownloadCount
    FROM dbo.tblDigitalMedia AS dm2
    LEFT OUTER JOIN dbo.tblDigitalMediaDownloads dl2
      ON dm2.FileID = dl2.FileID
    WHERE dl2.TimeStamp BETWEEN DATEADD(D, -365, GETDATE()) AND GETDATE()
    GROUP BY dm2.ProductID) AS DLs
      ON m.ProductID = DLs.ProductID

    LEFT OUTER JOIN dbo.tblDigitalMedia AS dm
      ON m.ProductID = dm.ProductID

    /* InventoryTemp should be called InventoryByLocation */
    LEFT OUTER JOIN dbo.InventoryTemp it2
      ON m.ProductID = it2.ProductID

    INNER JOIN dbo.StoredBy sb
      ON m.StoredByID = sb.StoredByID
    WHERE (m.edc_isle LIKE N'Aisle' + N'%'
    OR m.edc_isle = N'Digital Media'
    OR m.edc_isle = N'Duplicator')
    AND NOT (d.department_id BETWEEN 995 AND 999)

    GROUP BY m.ProductWeight,
             m.ProductID,
             m.reference_number,
             m.title,
             m.TotalInStock,
             dg.department_group_id,
             m.pub_date,
             m.department_id,
             d.department_code,
             m.pub_cost,
             m.RetailPrice,
             m.FullPubDate,
             m.edc_isle,
             sb.StoredBy,
             dg.department_group,
             CASE
               WHEN ISNULL(dm.FileID, 0) = 0 THEN 'N/A'
               ELSE 'Active'
             END,
             ISNULL(DLs.DownloadCount, 0),
             ISNULL(DLsCustom.DownloadCountCustom, 0),
             ISNULL(Boxes.Spaces, CASE
               WHEN sb.StoredBy = 'WWW' THEN 0
               ELSE 1
             END),
             m.edc_copies,
             ISNULL(m.number_of_pages, 'N/A')
    HAVING (NOT (MAX(sb.StoredBy) = @ShowNLA))
    ORDER BY m.FullPubDate) AS BaseInventory /* ***** Table A ***** */

    LEFT OUTER JOIN (SELECT
      dbo.shopping_cart.ProductID,
      SUM(dbo.shopping_cart.quantity) AS QuantitySold
    FROM dbo.orders
    INNER JOIN dbo.shopping_cart
      ON dbo.orders.receiving_number = dbo.shopping_cart.receiving_number
    WHERE dbo.orders.OrderTimeStamp >= DATEADD(DAY, -30, GETDATE())
    AND dbo.orders.OrderTimeStamp < GETDATE()
    AND dbo.shopping_cart.ProductID IS NOT NULL
    GROUP BY dbo.shopping_cart.ProductID) AS Sales30Days  /* ***** Table B ***** */
      ON BaseInventory.ProductID = Sales30Days.ProductID
    LEFT OUTER JOIN (SELECT
      dbo.shopping_cart.ProductID,
      SUM(dbo.shopping_cart.quantity) AS QuantitySold
    FROM dbo.orders
    INNER JOIN dbo.shopping_cart
      ON dbo.orders.receiving_number = dbo.shopping_cart.receiving_number
    WHERE @CustomDateStart IS NOT NULL
    AND dbo.orders.OrderTimeStamp >= @CustomDateStart
    AND dbo.orders.OrderTimeStamp <= @CustomDateEnd
    AND dbo.shopping_cart.ProductID IS NOT NULL
    GROUP BY dbo.shopping_cart.ProductID) AS CustomRangeSales /* ***** CustomRangeSales ***** */
      ON BaseInventory.ProductID = CustomRangeSales.ProductID

    LEFT OUTER JOIN (SELECT TOP (100) PERCENT
      cart3.ProductID,
      SUM(cart3.quantity) AS QuantitySold,
      m3.TotalInStock,
      CASE
        WHEN
          CONVERT(int, m3.TotalInStock / (CONVERT(decimal(18, 10), SUM(cart3.quantity)) / 365)) > ((9999 - YEAR(GETDATE())) * 365) THEN NULL
        ELSE CONVERT(varchar, DATEADD(DAY, CONVERT(int, m3.TotalInStock / (CONVERT(decimal(18, 10), SUM(cart3.quantity)) / 365)), GETDATE()), 101)
      END AS ZeroStock,
      CASE
        WHEN
          CONVERT(int, m3.TotalInStock / (CONVERT(decimal(18, 10), SUM(cart3.quantity)) / 365)) > ((9999 - YEAR(GETDATE())) * 365) THEN NULL
        ELSE DATEADD(DAY, CONVERT(int, m3.TotalInStock / (CONVERT(decimal(18, 10), SUM(cart3.quantity)) / 365)), GETDATE())
      END AS ZeroStockFullDate,
      CONVERT(decimal(18, 3), SUM(cart3.quantity) / ISNULL(CONVERT(decimal(18, 2), AvgInventory.NumberPerBox), SUM(cart3.quantity) + m3.TotalInStock)) AS SpacesSold,
      AvgInventory.NumberPerBox
    FROM dbo.orders AS o1
    INNER JOIN dbo.shopping_cart AS cart3
      ON o1.receiving_number = cart3.receiving_number
    INNER JOIN dbo.main AS m3
      ON cart3.ProductID = m3.ProductID
    LEFT OUTER JOIN (SELECT TOP (100) PERCENT
      ProductID,
      AVG(NumberPerBox) AS NumberPerBox
    FROM dbo.InventoryTemp
    GROUP BY ProductID
    ORDER BY ProductID) AS AvgInventory
      ON m3.ProductID = AvgInventory.ProductID
    WHERE (o1.OrderTimeStamp BETWEEN DATEADD(DAY, -365, GETDATE()) AND GETDATE() + 1)
    GROUP BY cart3.ProductID,
             m3.TotalInStock,
             AvgInventory.NumberPerBox
    HAVING (NOT (cart3.ProductID IS NULL))) AS SalesPastYear /* ***** Table C ***** */
      ON BaseInventory.ProductID = SalesPastYear.ProductID

    LEFT OUTER JOIN (SELECT
      ProductID,
      CASE
        WHEN ((Auth.Company = '') OR
          (Auth.Company IS NULL)) THEN LTRIM(ISNULL(Auth.FirstName, '') + ' ' + ISNULL(Auth.LastName, ''))
        ELSE Auth.Company
      END AS PrimaryAuthor
    FROM dbo.Author AS Auth
    INNER JOIN (SELECT
      AUTHLINK.AuthorID,
      AUTHLINK.Priority,
      AUTHLINK.ProductID
    FROM (SELECT TOP (100) PERCENT
      ProductID,
      MIN(ISNULL(Priority, 0)) AS Priority
    FROM dbo.AuthorLink
    GROUP BY ProductID
    ORDER BY ProductID) AS AuthMinPrty
    INNER JOIN dbo.AuthorLink AS AUTHLINK
      ON (AuthMinPrty.ProductID = AUTHLINK.ProductID)
      AND (ISNULL(AuthMinPrty.Priority, 0) = ISNULL(AUTHLINK.Priority, 0))) AS PrimaryAuthor
      ON Auth.AuthorID = PrimaryAuthor.AuthorID) AS vwAuthor /* Table Author */
      ON BaseInventory.ProductID = vwAuthor.ProductID

    ORDER BY BaseInventory.ReferenceNumber
  END
  ELSE
  BEGIN
    SELECT TOP (100) PERCENT
      BaseInventory.ProductID,
      BaseInventory.ReferenceNumber,
      BaseInventory.Title,
      BaseInventory.StoredBy,
      BaseInventory.TotalInStock,
      BaseInventory.StockAtEDC,
      BaseInventory.Cost,
      BaseInventory.RetailPrice,
      BaseInventory.PubDate,
      BaseInventory.DepartmentCode,
      vwAuthor.PrimaryAuthor,
      ISNULL(Sales30Days.QuantitySold, 0) AS Last30Days,
      ISNULL(SalesPastYear.QuantitySold, 0) AS Last365Days,
      ISNULL(CustomRangeSales.QuantitySold, 0) AS CustomRange,
      ISNULL(SalesPastYear.ZeroStock, '12/31/9999') AS ZeroStock,
      ISNULL(SalesPastYear.ZeroStockFullDate, CONVERT(datetime, '12/31/9999', 102)) AS ZeroStockFullDate,
      BaseInventory.FullPubDate,
      BaseInventory.ProgramArea,
      BaseInventory.Spaces,
      BaseInventory.DigitalFileExists,
      BaseInventory.DownloadCount,
      BaseInventory.DownloadCountCustom,
      ISNULL(SalesPastYear.SpacesSold, 0.000) AS SpacesSold,
      BaseInventory.DateReceived,
      BaseInventory.ProductWeight,
      BaseInventory.NumberOfPages,
      BaseInventory.DigitalFileCount,
      BaseInventory.ActiveDigitalFileCount
    FROM (SELECT TOP (100) PERCENT
      m.ProductWeight,
      m.ProductID,
      m.reference_number AS ReferenceNumber,
      m.title AS Title,
      MAX(sb.StoredBy) AS StoredBy,
      m.TotalInStock,
      m.edc_copies AS StockAtEDC,
      m.pub_cost AS Cost,
      m.RetailPrice,
      m.pub_date AS PubDate,
      d.department_code AS DepartmentCode,
      m.department_id AS DepartmentId,
      dg.department_group AS ProgramArea,
      m.FullPubDate,
      ISNULL(Boxes.Spaces, CASE
        WHEN sb.StoredBy = 'WWW' THEN 0
        ELSE 1
      END) AS Spaces,
      CASE
        WHEN ISNULL(dm.FileID, 0) = 0 THEN 'N/A'
        ELSE 'Active'
      END AS DigitalFileExists,
      ISNULL(DLs.DownloadCount, 0) AS DownloadCount,
      ISNULL(DLsCustom.DownloadCountCustom, 0) AS DownloadCountCustom,
      MAX(history.DateReceived) AS DateReceived,
      ISNULL(m.number_of_pages, 'N/A') AS NumberOfPages,
      (SELECT
        COUNT(*)
      FROM tblDigitalMedia tD
      WHERE tD.ProductID = m.ProductID)
      AS DigitalFileCount,
      (SELECT
        COUNT(*)
      FROM tblDigitalMedia tD
      WHERE tD.ProductID = m.ProductID
      AND tD.Active = 1)
      AS ActiveDigitalFileCount
    FROM dbo.main m
    INNER JOIN dbo.departments d
      ON m.department_id = d.department_id
    INNER JOIN dbo.department_groups dg
      ON d.department_group_id = dg.department_group_id

    /* InventoryTemp should be called InventoryByLocation */
    LEFT OUTER JOIN (SELECT
      m1.ProductID,
      SUM(ISNULL(it.NumberOfBoxes, 0)) + 1 AS Spaces
    FROM dbo.main AS m1
    INNER JOIN dbo.InventoryTemp AS it
      ON m1.ProductID = it.ProductID
    GROUP BY m1.ProductID) AS Boxes
      ON m.ProductID = Boxes.ProductID

    /* JobsTemp should be called JobHistory */
    LEFT OUTER JOIN dbo.JobsTemp history
      ON m.ProductID = history.ProductID

    LEFT OUTER JOIN (
    /* If dates are null then fetch for previous year. */
    SELECT TOP (100) PERCENT
      dm1.ProductID,
      COUNT(dl1.TimeStamp) AS DownloadCountCustom
    FROM dbo.tblDigitalMedia AS dm1
    LEFT OUTER JOIN dbo.tblDigitalMediaDownloads dl1
      ON dm1.FileID = dl1.FileID
    WHERE ((@CustomDateStart IS NOT NULL)
    AND (dl1.TimeStamp >= @CustomDateStart)
    AND (dl1.TimeStamp <= @CustomDateEnd))
    OR ((@CustomDateStart IS NULL)
    AND (dl1.TimeStamp BETWEEN DATEADD(D, -365, GETDATE()) AND GETDATE()))
    GROUP BY dm1.ProductID) AS DLsCustom
      ON m.ProductID = DLsCustom.ProductID
    LEFT OUTER JOIN (
    /* If dates are null then fetch for previous year. */
    SELECT TOP (100) PERCENT
      dm2.ProductID,
      COUNT(dl2.TimeStamp) AS DownloadCount
    FROM dbo.tblDigitalMedia AS dm2
    LEFT OUTER JOIN dbo.tblDigitalMediaDownloads dl2
      ON dm2.FileID = dl2.FileID
    WHERE dl2.TimeStamp BETWEEN DATEADD(D, -365, GETDATE()) AND GETDATE()
    GROUP BY dm2.ProductID) AS DLs
      ON m.ProductID = DLs.ProductID

    LEFT OUTER JOIN dbo.tblDigitalMedia AS dm
      ON m.ProductID = dm.ProductID

    /* InventoryTemp should be called InventoryByLocation */
    LEFT OUTER JOIN dbo.InventoryTemp it2
      ON m.ProductID = it2.ProductID

    INNER JOIN dbo.StoredBy sb
      ON m.StoredByID = sb.StoredByID
    WHERE (m.edc_isle LIKE N'Aisle' + N'%'
    OR m.edc_isle = N'Digital Media'
    OR m.edc_isle = N'Duplicator')
    AND (dg.department_group_id = @ProgramAreaID)

    GROUP BY m.ProductWeight,
             m.ProductID,
             m.reference_number,
             m.title,
             m.TotalInStock,
             dg.department_group_id,
             m.pub_date,
             m.department_id,
             d.department_code,
             m.pub_cost,
             m.RetailPrice,
             m.FullPubDate,
             m.edc_isle,
             sb.StoredBy,
             dg.department_group,
             CASE
               WHEN ISNULL(dm.FileID, 0) = 0 THEN 'N/A'
               ELSE 'Active'
             END,
             ISNULL(DLs.DownloadCount, 0),
             ISNULL(DLsCustom.DownloadCountCustom, 0),
             ISNULL(Boxes.Spaces, CASE
               WHEN sb.StoredBy = 'WWW' THEN 0
               ELSE 1
             END),
             m.edc_copies,
             ISNULL(m.number_of_pages, 'N/A')
    HAVING (NOT (MAX(sb.StoredBy) = @ShowNLA))
    ORDER BY m.FullPubDate) AS BaseInventory /* ***** Table A ***** */

    LEFT OUTER JOIN (SELECT
      dbo.shopping_cart.ProductID,
      SUM(dbo.shopping_cart.quantity) AS QuantitySold
    FROM dbo.orders
    INNER JOIN dbo.shopping_cart
      ON dbo.orders.receiving_number = dbo.shopping_cart.receiving_number
    WHERE dbo.orders.OrderTimeStamp >= DATEADD(DAY, -30, GETDATE())
    AND dbo.orders.OrderTimeStamp < GETDATE()
    AND dbo.shopping_cart.ProductID IS NOT NULL
    GROUP BY dbo.shopping_cart.ProductID) AS Sales30Days  /* ***** Table B ***** */
      ON BaseInventory.ProductID = Sales30Days.ProductID
    LEFT OUTER JOIN (SELECT
      dbo.shopping_cart.ProductID,
      SUM(dbo.shopping_cart.quantity) AS QuantitySold
    FROM dbo.orders
    INNER JOIN dbo.shopping_cart
      ON dbo.orders.receiving_number = dbo.shopping_cart.receiving_number
    WHERE @CustomDateStart IS NOT NULL
    AND dbo.orders.OrderTimeStamp >= @CustomDateStart
    AND dbo.orders.OrderTimeStamp <= @CustomDateEnd
    AND dbo.shopping_cart.ProductID IS NOT NULL
    GROUP BY dbo.shopping_cart.ProductID) AS CustomRangeSales /* ***** CustomRangeSales ***** */
      ON BaseInventory.ProductID = CustomRangeSales.ProductID

    LEFT OUTER JOIN (SELECT TOP (100) PERCENT
      cart3.ProductID,
      SUM(cart3.quantity) AS QuantitySold,
      m3.TotalInStock,
      CASE
        WHEN
          CONVERT(int, m3.TotalInStock / (CONVERT(decimal(18, 10), SUM(cart3.quantity)) / 365)) > ((9999 - YEAR(GETDATE())) * 365) THEN NULL
        ELSE CONVERT(varchar, DATEADD(DAY, CONVERT(int, m3.TotalInStock / (CONVERT(decimal(18, 10), SUM(cart3.quantity)) / 365)), GETDATE()), 101)
      END AS ZeroStock,
      CASE
        WHEN
          CONVERT(int, m3.TotalInStock / (CONVERT(decimal(18, 10), SUM(cart3.quantity)) / 365)) > ((9999 - YEAR(GETDATE())) * 365) THEN NULL
        ELSE DATEADD(DAY, CONVERT(int, m3.TotalInStock / (CONVERT(decimal(18, 10), SUM(cart3.quantity)) / 365)), GETDATE())
      END AS ZeroStockFullDate,
      CONVERT(decimal(18, 3), SUM(cart3.quantity) / ISNULL(CONVERT(decimal(18, 2), AvgInventory.NumberPerBox), SUM(cart3.quantity) + m3.TotalInStock)) AS SpacesSold,
      AvgInventory.NumberPerBox
    FROM dbo.orders AS o1
    INNER JOIN dbo.shopping_cart AS cart3
      ON o1.receiving_number = cart3.receiving_number
    INNER JOIN dbo.main AS m3
      ON cart3.ProductID = m3.ProductID
    LEFT OUTER JOIN (SELECT TOP (100) PERCENT
      ProductID,
      AVG(NumberPerBox) AS NumberPerBox
    FROM dbo.InventoryTemp
    GROUP BY ProductID
    ORDER BY ProductID) AS AvgInventory
      ON m3.ProductID = AvgInventory.ProductID
    WHERE (o1.OrderTimeStamp BETWEEN DATEADD(DAY, -365, GETDATE()) AND GETDATE() + 1)
    GROUP BY cart3.ProductID,
             m3.TotalInStock,
             AvgInventory.NumberPerBox
    HAVING (NOT (cart3.ProductID IS NULL))) AS SalesPastYear /* ***** Table C ***** */
      ON BaseInventory.ProductID = SalesPastYear.ProductID

    LEFT OUTER JOIN (SELECT
      ProductID,
      CASE
        WHEN ((Auth.Company = '') OR
          (Auth.Company IS NULL)) THEN LTRIM(ISNULL(Auth.FirstName, '') + ' ' + ISNULL(Auth.LastName, ''))
        ELSE Auth.Company
      END AS PrimaryAuthor
    FROM dbo.Author AS Auth
    INNER JOIN (SELECT
      AUTHLINK.AuthorID,
      AUTHLINK.Priority,
      AUTHLINK.ProductID
    FROM (SELECT TOP (100) PERCENT
      ProductID,
      MIN(ISNULL(Priority, 0)) AS Priority
    FROM dbo.AuthorLink
    GROUP BY ProductID
    ORDER BY ProductID) AS AuthMinPrty
    INNER JOIN dbo.AuthorLink AS AUTHLINK
      ON (AuthMinPrty.ProductID = AUTHLINK.ProductID)
      AND (ISNULL(AuthMinPrty.Priority, 0) = ISNULL(AUTHLINK.Priority, 0))) AS PrimaryAuthor
      ON Auth.AuthorID = PrimaryAuthor.AuthorID) AS vwAuthor /* Table Author */
      ON BaseInventory.ProductID = vwAuthor.ProductID

    ORDER BY BaseInventory.ReferenceNumber
  END
END /* stored procedure */
GO

1 Ответ

0 голосов
/ 01 октября 2018

Не обращайте внимания на всех людей, которые говорят вам сделать это другим способом, и посмотрите, сможете ли вы настроить то, что у вас есть.Человек, который заявил, что это 4 запроса, является неправильным.LINQ будет объединен в один оператор SQL.Что вам нужно сделать, это попытаться выяснить:

  • Как выглядит сгенерированный SQL (попробуйте захватить его с помощью SQL Server Profiler)
  • Почему он неэффективен (опять же, SQLПрофилировщик сервера или вставьте его в SSMS и покажите план запроса)

После того, как вы это сделаете, вам может стать понятнее, что вам нужно сделать с LINQ, чтобы он работал.

Одна вещь, которую вы можете попробовать, чтобы упростить количество, которое вам нужно посмотреть за один раз: выполнить каждый «внутренний» запрос изолированно и посмотреть, не выглядит ли какой-либо из них сам по себе плохо.

...