I want to convert ROW_NUMBER()OVER(PARTION BY) to LINQ.

Asked 2 years ago, Updated 2 years ago, 97 views

Thank you for always taking care of me.
I want to get the same results as the SQL below on LINQ, but I'm struggling because I can't meet my expectations.

I tried to create it based on the information here, but the difference is that there are three partitions, and I expect that there is a mistake in the nested part of foreach, but I have not been able to get the expected value.

What do you want to know?
Is it possible to use a compound key with ROW_NUMBER()OVER(PARTMENT BY) in LINQ?
After the LEFT JOIN, the grouping is done in SQL, so I'm doing it in that order, but is it correct?
Is the nesting of foreach correct?
Yes.
I would appreciate it if you could teach me

TMP1
    ID int
    START_DATE datetime
    TOUROKU_NO INT
    CD string

TMP2
    ID int
    START_DATE datetime
    TOUROKU_NO INT
    CD string
    END_DATE datetime
SELECT
    BB4.ID,
    BB4. [START_DATE],
    BB4. [TOUROKU_NO],
    MAX (CASE WHEN BB4. [RN] = 1 THEEN BB4. [CD] ELSE' 'END) AS [CD],
    MAX (CASE WHEN BB4. [RN] = 1 THEEN BB4. [END_DATE] ELSE' 'END) AS [END_DATE]
FROM(
    SELECT
        *,
        ROW_NUMBER() OVER (Partition BY BB3. [ID], BB3. [START_DATE], BB3. [TOUROKU_NO] ORDER BY BB3. [END_DATE] AS [RN]
    FROM(
        SELECT
            BB1.*,
            CASE WHEN BB2. [START_DATE] is NULL THE GETDATE() ELSE BB2. [START_DATE] ENDAS [END_DATE]
        FROM# TMP1 AS BB1
        LEFT JOIN# TMP1AS BB2 ON (BB1.[ID] = BB2.[ID]AND BB1.[TOUROKU_NO] = BB2.[TOUROKU_NO]AND BB1.[START_DATE]<BB2.[START_DATE])
    AS BB3
AS BB4
GROUP BY BB4. [ID], BB4. [START_DATE], BB4. [TOUROKU_NO]
//Self-coupling
     var joinTable=from a in TMP1
        join a2 in TMP1
        on a.ID equals a2.ID intog
         from a2ing.DefaultIfEmpty()
        where a.TOUROKU_NO==a2.TOUROKU_NO&a.START_DATE<a2.START_DATE
        select new {
            a.ID,
            a. START_DATE,
            a. TOUROKU_NO,
            a.CD,
            END_DATE=(DBNull.Value.Equals(a2.START_DATE)?(DateTime)a2.SERVERDATE:(DateTime)a2.START_DATE)
        };


// Grouping
var groupTable = from a in joinTable
                 group by new {a.ID, a.START_DATE, a.TOUROKU_NO} intog
                 select new {
                     ID = from Ming
                                select m.ID,
                     START_DATE = g.Key.START_DATE,
                     TOUROKU_NO=g.Key.TOUROKU_NO,
                     CD = from Ming
                           select m.CD,
                     END_DATE=fromming
                                orderbym.END_DATE
                                select m.END_DATE
                 };

foreach (varitem in groupTable) {
    foreach(varid in item.ID) {
        foreach(varcd in item.CD){
            foreach(var end_date in item.END_DATE){
                varRow=DataTable.NewRow();
                Row[0] = id.ToString();
                Row[1] = DatePicker(item.START_DATE.ToString());
                Row[2] = Convert.ToInt32 (item.TOUROKU_NO);
                Row[3] = cd.ToString();
                Row[4] = DatePicker(end_date.ToString());
                DataTable.Rows.Add (Row);
            }
        }
    }
}

Additional information

SELECT
            BB1.*,
            CASE WHEN BB2. [START_DATE] is NULL THE GETDATE() ELSE BB2. [START_DATE] ENDAS [END_DATE]
        FROM TMP1 AS BB1
        LEFT JOIN TMP1 AS BB2 ON (BB1.[id] = BB2.[id] AND BB1. [TOUROKU_NO] = BB2. [TOUROKU_NO] AND BB1. [START_DATE] <BB2. [START_DATE])
ID STARTDATE TOROKU_NO CD END_DATE               
7   2010-06-30 00:00:00.000 1           03010,                          2011-07-05 00:00:00.000
7   2010-06-30 00:00.000    1           03010,                          2011-09-26 00:00:00.000
7   2010-06-30 00:00:00.000 1           03010,                          2011-12-06 00:00:00.000
7   2010-06-30 00:00:00.000 2           02010,                          2011-12-06 00:00:00.000
7   2010-06-30 00:00:00.000 3           10010,                          2016-11-01 14:48:08.410
7   2010-06-30 00:00:00.000 4           04441,                          2016-11-01 14:48:08.410
7   2011-07-05 00:00:00.000 1           09010,                          2011-09-26 00:00:00.000
7   2011-07-05 00:00:00.000 1           09010,                          2011-12-06 00:00:00.000
7   2011-09-26 00:00:00.000 1           10010,                          2011-12-06 00:00:00.000
7   2011-12-06 00:00:00.000 1           09010,                          2016-11-01 14:48:08.410
7   2011-12-06 00:00:00.000 2           04441,                          2016-11-01 14:48:08.410
10  2010-04-28 00:00:00.000 1           02310,                          2012-01-23 00:00:00.000
10  2010-04-28 00:00:00.000 1           02310,                          2010-10-25 00:00:00.000
10  2010-04-28 00:00:00.000 1           02310,                          2011-02-07 00:00:00.000
10  2010-04-28 00:00:00.000 1           02310,                          2011-10-12 00:00:00.000
10  2010-10-25 00:00:00.000 1           02310,                          2012-01-23 00:00:00.000

Convert SQL1 to linq

var joinTable=from a in TMP1
        join a2 in TMP1
        on a.ID equals a2.ID intog
         from a2ing.DefaultIfEmpty()
        where a.TOUROKU_NO==a2.TOUROKU_NO&a.START_DATE<a2.START_DATE
        select new {
            a.ID,
            a. START_DATE,
            a. TOUROKU_NO,
            a.CD,
            END_DATE=(DBNull.Value.Equals(a2.START_DATE)?(DateTime)a2.SERVERDATE:(DateTime)a2.START_DATE)
        };

            foreach(var item in joinTable) {
                    ID = item.ID.ToString();
                    START_DATE = item.START_DATE;
                    TOUROKU_NO=item.TOUROKU_NO;
                    CD=item.CD.ToString();
                    END_DATE = item.END_DATE;
                }
ID STARTDATE TOROKU_NO CD END_DATE       
    7   2010/06/30 0:00:00      1          03010,     2011/07/05 0:00:00
    7   2010/06/30 0:00:00      1          03010,     2011/09/26 0:00:00
    7   2010/06/30 0:00:00      1          03010,     2011/12/06 0:00:00
    7   2010/06/30 0:00:00      2          02010,     2011/12/06 0:00:00
    7   2011/07/05 0:00:00      1          09010,     2011/09/26 0:00:00
    7   2011/07/05 0:00:00      1          09010,     2011/12/06 0:00:00
    7   2011/09/26 0:00:00      1          10010,     2011/12/06 0:00:00
    10  2010/04/28 0:00:00      1          02310,     2010/10/25 0:00:00
    10  2010/04/28 0:00:00      1          02310,     2011/02/07 0:00:00
    10  2010/04/28 0:00:00      1          02310,     2011/10/12 0:00:00
    10  2010/04/28 0:00:00      1          02310,     2012/01/23 0:00:00
    10  2010/10/25 0:00:00      1          02310,     2011/02/07 0:00:00
    10  2010/10/25 0:00:00      1          02310,     2011/10/12 0:00:00
    10  2010/10/25 0:00:00      1          02310,     2012/01/23 0:00:00
    10  2011/02/07 0:00:00      1          02310,     2011/10/12 0:00:00
    10  2011/02/07 0:00:00      1          02310,     2012/01/23 0:00:00

I would like to self-join with leftjoin, but it didn't work like the SQL results above.
How do I write linq to get the same value as SQL1?
SQL2
        SELECT
            *,
        ROW_NUMBER() OVER (Partition BY BB3. [id], BB3. [START_DATE], BB3. [TOUROKU_NO] ORDER BY BB3. [END_DATE] AS [RN]
        FROM(
            SELECT
                BB1.*,
                CASE WHEN BB2. [START_DATE] is NULL THE GETDATE() ELSE BB2. [START_DATE] ENDAS [END_DATE]
            FROM TMP1 AS BB1
            LEFT JOIN TMP1 AS BB2 ON (BB1.[id] = BB2.[id] AND BB1. [TOUROKU_NO] = BB2. [TOUROKU_NO] AND BB1. [START_DATE] <BB2. [START_DATE])
        AS BB3
ID STARTDATE TOROKU_NO CD END_DATERN
7   2010-06-30 00:00:00.000 1           03008,                          2011-07-05 00:00:00.000      1
7   2010-06-30 00:00:00.000 1           03009,                          2011-09-26 00:00:00.000      2
7   2010-06-30 00:00:00.000 1           03009,                          2011-12-06 00:00:00.000      3
7   2010-06-30 00:00:00.000 2           02009,                          2011-12-06 00:00:00.000      1
7   2010-06-30 00:00:00.000 3           10009,                          2016-11-01 14:50:38.060      1
7   2010-06-30 00:00:00.000 4           04440,                          2016-11-01 14:50:38.060      1
7   2011-07-05 00:00:00.000 1           09010,                          2011-09-26 00:00:00.000      1
7   2011-07-05 00:00:00.000 1           09010,                          2011-12-06 00:00:00.000      2
7   2011-09-26 00:00:00.000 1           10010,                          2011-12-06 00:00:00.000      1
7   2011-12-06 00:00:00.000 1           09010,                          2016-11-01 14:50:38.060      1
7   2011-12-06 00:00:00.000 2           04441,                          2016-11-01 14:50:38.060      1
10  2010-04-28 00:00:00.000 1           02310,                          2010-10-25 00:00:00.000      1
10  2010-04-28 00:00:00.000 1           02310,                          2011-02-07 00:00:00.000      2
10  2010-04-28 00:00:00.000 1           02310,                          2011-10-12 00:00:00.000      3
10  2010-04-28 00:00:00.000 1           02310,                          2012-01-23 00:00:00.000      4
10  2010-10-25 00:00:00.000 1           02310,                          2011-02-07 00:00:00.000      1
10  2010-10-25 00:00:00.000 1           02310,                          2011-10-12 00:00:00.000      2
10  2010-10-25 00:00:00.000 1           02310,                          2012-01-23 00:00:00.000      3
10  2011-02-07 00:00:00.000 1           02310,                          2011-10-12 00:00:00.000      1
10  2011-02-07 00:00:00.000 1           02310,                          2012-01-23 00:00:00.000      2
10  2011-02-07 00:00:00.000 2           02310,03020,18010,            2016-11-01 14:50:38.060        1
10  2011-02-07 00:00:00.000 3           20010,02030,                    2016-11-01 14:50:38.060      1
10  2011-02-07 00:00:00.000 4           01210,                          2016-11-01 14:50:38.060      1
10  2011-02-07 00:00:00.000 5           02010,                          2016-11-01 14:50:38.060      1
10  2011-02-07 00:00:00.000 6           20010,                          2016-11-01 14:50:38.060      1
10  2011-02-07 00:00:00.000 7           02030,                          2016-11-01 14:50:38.060      1
10  2011-10-12 00:00:00.000 1           02310,                          2012-01-23 00:00:00.000      1
10  2012-01-23 00:00:00.000 1           02310,                          2016-11-01 14:50:38.060      1
11  2010-04-28 00:00:00.000 1           02310,                          2010-10-25 00:00:00.000      1
11  2010-04-28 00:00:00.000 1           02310,                          2011-02-07 00:00:00.000      2
11  2010-04-28 00:00:00.000 1           02310,                          2011-06-27 00:00:00.000      3
11  2010-04-28 00:00:00.000 1           02310,                          2011-10-12 00:00:00.000   4
11  2010-04-28 00:00:00.000 1           02310,                          2012-01-23 00:00:00.000      5
    11  2010-10-25 00:00:00.000 1           02310,                          2011-02-07 00:00:00.000      1
11  2010-10-25 00:00:00.000 1           02310,                          2011-06-27 00:00:00.000      2
SQL3
    SELECT
        BB4.[id],
        BB4. [START_DATE],
        BB4. [TOUROKU_NO],
        MAX (CASE WHEN BB4. [RN] = 1 THEEN BB4. [CD] ELSE' 'END) AS [CD],
        MAX (CASE WHEN BB4. [RN] = 1 THEEN BB4. [END_DATE] ELSE' 'END) AS [END_DATE]
        From(
        SELECT
            *,
        ROW_NUMBER() OVER (Partition BY BB3. [id], BB3. [START_DATE], BB3. [TOUROKU_NO] ORDER BY BB3. [END_DATE] AS [RN]
        FROM(
            SELECT
                BB1.*,
                CASE WHEN BB2. [START_DATE] is NULL THE GETDATE() ELSE BB2. [START_DATE] ENDAS [END_DATE]
            FROM TMP1 AS BB1
            LEFT JOIN TMP1 AS BB2 ON (BB1.[id] = BB2.[id] AND BB1. [TOUROKU_NO] = BB2. [TOUROKU_NO] AND BB1. [START_DATE] <BB2. [START_DATE])
        AS BB3
    AS BB4
        GROUP BY BB4. [id], BB4. [START_DATE], BB4. [TOUROKU_NO]

This is the final data I want to get.

ID STARTDATE TOROKU_NO CD END_DATE                     
7   2010-06-30 00:00:00.000 1           03010,                          2011-07-05 00:00:00.000
7   2010-06-30 00:00:00.000 2           02010,                          2011-12-06 00:00:00.000
7   2010-06-30 00:00:00.000 3           10010,                          2016-11-01 14:53:38.593
7   2010-06-30 00:00:00.000 4           04441,                          2016-11-01 14:53:38.593
7   2011-07-05 00:00:00.000 1           09010,                          2011-09-26 00:00:00.000
7   2011-09-26 00:00:00.000 1           10010,                          2011-12-06 00:00:00.000
7   2011-12-06 00:00:00.000 1           09010,                          2016-11-01 14:53:38.593
7   2011-12-06 00:00:00.000 2           04441,                          2016-11-01 14:53:38.593
10  2010-04-28 00:00:00.000 1           02310,                          2010-10-25 00:00:00.000
10  2010-10-25 00:00:00.000 1           02310,                          2011-02-07 00:00:00.000
10  2011-02-07 00:00:00.000 1           02310,                          2011-10-12 00:00:00.000
10  2011-02-07 00:00:00.000 2           02310,03020,18010,              2016-11-01 14:53:38.593
10  2011-02-07 00:00:00.000 3           20010,02030,                    2016-11-01 14:53:38.593
10  2011-02-07 00:00:00.000 4           01210,                          2016-11-01 14:53:38.593
10  2011-02-07 00:00:00.000 5           02010,                          2016-11-01 14:53:38.593
10  2011-02-07 00:00:00.000 6           20010,                          2016-11-01 14:53:38.593
10  2011-02-07 00:00:00.000 7           02030,                          2016-11-01 14:53:38.593
10  2011-10-12 00:00:00.000 1           02310,                          2012-01-23 00:00:00.000
10  2012-01-23 00:00:00.000 1           02310,                          2016-11-01 14:53:38.593
11  2010-04-28 00:00:00.000 1           02310,                          2010-10-25 00:00:00.000
11  2010-10-25 00:00:00.000 1           02310,                          2011-02-07 00:00:00.000
11  2011-02-07 00:00:00.000 1           02310,                          2011-06-27 00:00:00.000
11  2011-06-27 00:00:00.000 1           02310,                          2011-10-12 00:00:00.000
11  2011-10-12 00:00:00.000 1           02310,                          2012-01-23 00:00:00.000

I look forward to your kind cooperation.

c# sql linq

2022-09-30 21:19

1 Answers

ROW_NUMBER()The analysis function is basically not supported by EntityFramework, but this time the partition matches the grouping target.

foreach(var end_date in item.END_DATE) {

If you add the Enumerable.Select extension method of LINQ to Object to the

item.END_DATE.Select((d,i)=>new{RN=i+1,end_date=d})

You can obtain the line number as shown in .Or simply

varrn=0;
foreach(var end_date in item.END_DATE){
    rn++;

and variables are also available.

I didn't scrutinize SQL, but basically there should be no problem.

I don't know the specifications, but maybe

foreach(varid in item.ID) {

The item.ID in is a grouping key, so it is all equivalent and unnecessary.

As for SQL in the questionnaire, I think it would be good if we could extract the record with the smallest END_DATE in each group, so I think we can achieve the goal with LINQ as follows.

//Grouping
var groupTable = from a in joinTable
                 // Sort by (group key +) END_DATE
                 orderby a.ID, a.START_DATE, a.TOUROKU_NO, a.END_DATE
                 group by new {a.ID, a.START_DATE, a.TOUROKU_NO} intog
                 select g.FirstOrDefault();

joinTable is a sub-question

var joinTable=from origin in TMP1
                select new
                {
                    origin.ID,
                    origin.START_DATE,
                    origin.TOUROKU_NO,
                    origin.CD,
                    END_DATE=TMP1.Where(alias=>orig.ID==alias.ID
                                        &orig.TOUROKU_NO==alias.TOUROKU_NO
                                        &orig.START_DATE<alias.START_DATE)
                                    .Min(_=>(DateTime?)_.START_DATE)
                                   ?? DateTime.Now
                };

It can be written as shown in .In the above two queries, ???DateTime.Now and selectg.FirstOrDefault() of END_DATE are the bottlenecks, so

  • END_DATE==START_DATE decision later.
  • Make a of
  • groupa a special type, and eliminate selectg.FirstOrDefault() including MIN(END_DATE).

I think it will be faster if you take policies such as .


2022-09-30 21:19

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.