объединение влево с одной строкой в ​​правой таблице в LINQ - PullRequest
2 голосов
/ 09 января 2020

Hifriends, у меня есть одна таблица клиентов и одна таблица отношений, где я храню клиентов, которым я отправляю ссылку на опрос. Один и тот же опрос мог быть отправлен одному и тому же клиенту более одного раза. Или некоторые клиенты, возможно, не отправили ссылки на опрос. моя цель состоит в том, чтобы собрать всех клиентов один раз, и если некоторым из этих клиентов была отправлена ​​анкета, я хочу, чтобы только один из них создал дату, которая является самой большой. Количество записей должно быть равно количеству клиентов. Я написал запрос, но очень трудно перевести linq или. Вы можете помочь.

это запрос, который я написал

SELECT *
FROM dbo.Customer c
 LEFT JOIN dbo.SurveyCustomers sc ON sc.SurveyCustomerId =
(
SELECT A.SurveyCustomerId
FROM
(
    SELECT TOP 1 *
    FROM dbo.SurveyCustomers sc1
    WHERE sc1.STATUS = 1
          AND sc1.IsActive = 1
          AND sc1.CustomerId = c.CustomerId
          AND sc1.SurveyId = 1207
          AND sc1.STATUS = 1
          AND sc1.IsActive = 1
    ORDER BY sc1.CreatedDate DESC
) A
)
WHERE c.IsActive = 1
  AND c.STATUS = 1;

Таблица клиентов

CREATE TABLE [dbo].[Customer](
[CustomerId] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[CustomerTitle] [varchar](500) NOT NULL,
[CustomerEmail] [varchar](500) NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[UpdatedDate] [datetime] NOT NULL,
[IsActive] [bit] NOT NULL,
[Status] [bit] NOT NULL)

SurveyCustomer

CREATE TABLE [dbo].[SurveyCustomers](
[SurveyCustomerId] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[SurveyId] [int] NOT NULL FOREIGN KEY,
[CustomerId] [int] NOT NULL FOREIGN KEY,
[GuidId] [varchar](500) NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[UpdatedDate] [datetime] NOT NULL,
[Status] [bit] NOT NULL,
[IsActive] [bit] NOT NULL)

Ответы [ 3 ]

0 голосов
/ 09 января 2020

Вы можете сделать это:

var finalSurveyCustomers = from customer in Customers
                           join sc in SurveyCustomers on customer.CustomerId equals sc.SurveyCustomerId into leftCustomers
                           from leftCustomer in leftCustomers.DefaultIfEmpty()
                           select new { LeftId = customer.Id, SurveyId = leftCustomer ?? 0 }; // can use int.Max or int.Min
0 голосов
/ 09 января 2020

Вы можете использовать OUTER APPLY для получения того же результата.

SELECT *
FROM dbo.Customer c
 OUTER APPLY 
(
    SELECT TOP 1 *
    FROM dbo.SurveyCustomers sc1
    WHERE sc1.STATUS = 1
          AND sc1.IsActive = 1
          AND sc1.CustomerId = c.CustomerId
          AND sc1.SurveyId = 1207
    ORDER BY sc1.CreatedDate DESC
) A
WHERE c.IsActive = 1
  AND c.STATUS = 1;

и эквивалент linq:

Customers.SelectMany(c => SurveyCustomers
                        .Where(sc1 => 
                            sc1.Status == true 
                            && sc1.IsActive == true
                            && sc1.CustomerId == c.CustomerId
                            && sc1.SurveyId == 1207 )
                        .OrderByDescending(sc1 => sc1.CreatedDate)
                        .Take(1).DefaultIfEmpty(), 
                    (c, sc) => new { c, sc })
.ToList()
0 голосов
/ 09 января 2020

Для этих случаев вам нужно предложение GROUP BY:

SELECT c.SurveyCustomerId, MAX( /* THE MAX YOU WANT TO GET */)
FROM dbo.Customer c
 LEFT JOIN dbo.SurveyCustomers sc ON sc.SurveyCustomerId = A.SurveyCustomerId
GROUP BY c.SurveyCustomerId
WHERE c.IsActive = 1 AND c.STATUS = 1 /*AND OTHER CONDITIONS */;

Дополнительная информация по классу GROUP BY:

https://docs.microsoft.com/en-us/sql/t-sql/queries/select-group-by-transact-sql?view=sql-server-ver15

Обновление: Извините, пропустил часть LINQ: Вы должны сделать что-то вроде этого:

public class SurveyCustomer
    {
        public int SurveyCustomerId { get; set; }

        public virtual ICollection<Survey> Surveys { get; set; }
    }

    public class Survey
    {
        public int SurveyId { get; set; }
    }

    public class SurveyCustomerReadModel
    {
        public int SurveyCustomerId { get; set; }

        public int LastSurveyId { get; set; }
    }

    public class SurveyCustomerRepository
    {
        public List<SurveyCustomer> SurveyCustomers { get; set; }

        public IEnumerable<SurveyCustomerReadModel> GetSurveyCustomerReadModel()
        {
            return this.SurveyCustomers
                .Select(sc => new SurveyCustomerReadModel
                {
                    SurveyCustomerId = sc.SurveyCustomerId,
                    LastSurveyId = sc.Surveys.Max(/* SOME CRITERIA FOR DEFINING THE MAX*/).SurveyId
                });
        }
    }

С уважением!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...