Как я могу отсортировать подсчитанные строки данных в соответствии с определенным параметром

#c# #sorting #datatable

Вопрос:

Я пытаюсь использовать dataTable.Rows.Count , но сортирую результат на основе определенного параметра. Этот параметр является «Столбцом 1» в моем DataTable . Так что на выходе я получаю строки, относящиеся только к этому отдельному значению. Мой DataTable находится в a View , но мне нужно использовать отсортированные int значения в a ViewModel .

Я могу сосчитать строки с public static int o { get; set; } и а dt.Rows.Count в моем DataTable . Затем я получаю значение , создав экземпляр my View в my ViewModel , with int numberOfRows = ViewName.o; .

Но это дает мне общее количество строк, тогда как мне нужно количество строк на каждое отдельное значение в «Столбце 1».

Мой вопрос в том, где и как я могу выполнить необходимую сортировку? Потому что, когда я зашел так далеко, чтобы сосчитать их и добавить в int (в моем ViewModel ), нет никакого способа узнать, какую строку они представляли, верно? И если я попытаюсь как-то отсортировать DataTable View ), я не знаю, как ссылаться на различные значения. Они могут время от времени меняться по мере использования программы, поэтому я не могу жестко ее закодировать.

Комментарий предложил вместо этого использовать запрос, добавив мою хранимую процедуру для помощи в реализации решения:

 SET NOCOUNT ON
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[myProcedure]
    @param myUserDefinedTableType readonly

AS
BEGIN TRANSACTION
    INSERT INTO [dbo].[myTable] (/* list of columns */)
        SELECT [Column1], /* this is the column I need to sort by */
               -- more columns
               -- the rest of the columns
        /* I do aggregations to my columns here, I am adding several thousands row to 20 summarized rows, so after this line, I can no longer get ALL the rows per "Column1", but only the summarized rows. How can I count the rows BEFORE I do the aggregations? */
        FROM @param

        GROUP BY [Column2], [Column1]
        ORDER BY [Column2], [Column1]

// Some UPDATE clauses

COMMIT TRANSACTION
 

Ответ №1:

Я считаю, что самый мудрый выбор-действовать на стороне бд.
Предполагая, что вы используете SQL Server, запрос должен быть:

 SELECT *, COUNT(*) OVER (PARTITION BY Column1) AS c
FROM Table1
ORDER BY c
 

Этот запрос возвращает данные вашей таблицы «Table1» плюс столбец «c», представляющий количество значений «Column1» для каждой строки.
Наконец, он сортирует строки по столбцу «c», как вы просите.


Редактировать

Для выполнения этой задачи я буду использовать Общее табличное выражение:

 -- Code before INSERT...

;WITH CTE1 AS (  
    SELECT *,  
        COUNT(*) OVER (PARTITION BY [Column1]) AS c  
    FROM @param  
)  
INSERT INTO [dbo].[myTable] (/* list of columns - must add the column c */)  
SELECT [Column1],  
       [Column2],  
       [c],  
       -- aggregated columns    
FROM CTE1  
GROUP BY [Column2], [Column1], c  
      
-- Code after INSERT...  
 

В общем табличном выражении «CTE1» я выбираю все значения в @param, добавляя столбец «c» с количеством на столбец 1.

Примечание: если у вас есть 5 строк с одинаковым значением Столбец1, но два разных значения в Столбец2, в таблице mytable у вас будет две строки (из-за группы [Столбец2], [Столбец1]), как при c=5.
Если вы хотите, вместо того, чтобы получить количество сгруппированы по Столбец1 и Столбец2, вы должны объявить с следующим образом: COUNT(*) OVER (PARTITION BY [Column1], [Column2]) AS c .

Надеюсь, я выразился ясно, если нет, я могу объяснить это по-другому.


пример

 CREATE TABLE myTable (col1 VARCHAR(50), col2 INT, col3 INT, c INT) 

CREATE TYPE myUserDefinedTableType AS TABLE (column1 VARCHAR(50), column2 INT,  column3 INT)  
DECLARE @param myUserDefinedTableType  
INSERT INTO @param VALUES ('A', 1, 4), ('A', 2, 3), ('A', 2, 6), ('B', 2, 3)  

;WITH CTE1 AS (
    SELECT *, COUNT(*) OVER (PARTITION BY [Column1]) AS c 
    FROM @param
)  
INSERT INTO [myTable]([col1], [col2], [col3], [c])  
SELECT [column1], [column2], 
    -- aggregated columns  
    MAX([column3]), 
    -- count
    [c]  
FROM CTE1  
GROUP BY [column2], [column1], c   
 

Комментарии:

1. Спасибо за ваш комментарий! Я добавил свою хранимую процедуру в свой вопрос, так как не могу реализовать ваше решение. Если бы вы взглянули, это было бы здорово!

2. Я отредактировал исходный ответ, чтобы ответить на ваши последние запросы.

3. Это интересно! Я получаю ошибку с недопустимым именем столбца «c». Я предполагаю, что сначала мне нужно добавить столбец в мою таблицу и мой пользовательский тип таблицы (@param)?

4. Привет, только в таблице «Мой стол». Кроме того, обязательно объявите поле в CTE с синтаксисом COUNT(*) OVER (PARTITION BY [Column1]) AS c .

5. Самуэле, спасибо за вашу постоянную помощь! Я получаю сообщение об ошибке > Попытка передать параметр с табличным значением с 14 столбцами, где для соответствующего пользовательского типа таблицы требуется 13 столбцов. Если я также обновлю UDTT столбцом c, я получу сообщение об ошибке, в котором говорится, что столбец удалялся слишком много раз (или что-то в этом роде).

Ответ №2:

 DataView dv = dt.DefaultView;
dv.Sort = "SName ASC"; -- your column name
DataTable dtsorted = dv.ToTable();

 DataTable dtsorted = dv.ToTable(true, "Sname","Surl" ); //return distinct rows
 

Комментарии:

1. Я не вижу, как это решает мою проблему (мне нужно подсчитать общее количество строк на каждое отдельное значение в «Столбце 1»). Не хотите уточнить?

2. @user16600932 обновил код для различных значений