Страница: 1 |
Страница: 1 |
Вопрос: кто знает (расширенная сорировка)?
Добавлено: 26.10.06 17:10
Автор вопроса: Marki
Кто может помочь с ответом на вопрос:
-----
имеется объект DataGridView с несколькими столбцами.
В него заливаются данные, полученные путем запроса SQL с указанием сортировки по нескольким столбцам.
В результате изменения данных необходима их пересортировка для сохранения порядка отображения.
Каим образом отсортировать по нескольким столбцам одновременно?
сортировка требуется по ТРЕМ столбцам.
-----
например, есть столбец "город", "улица", "фамилия".
условно говоря при переезде человека с адреса на адрес или с города в город его положение в списке изменялось. Ну или если человек, например, сменил фамилию )))
Ответы
Всего ответов: 15
Номер ответа: 1
Автор ответа:
AKE
Вопросов: 0
Ответов: 7
Профиль | | #1
Добавлено: 26.10.06 23:09
Создай в таблице(таблицах) дополнительное поле (например SORT_ORDER)заполни его как тебе нужно и сортируй по нему! В Select-e это поле можно не указывать, или сделать ширину колонки=0... Вообще то непонятно, при смене фамилии -нужно менять положение или нет!?
Номер ответа: 2
Автор ответа:
Marki
Вопросов: 42
Ответов: 94
Профиль | | #2
Добавлено: 26.10.06 23:21
еще раз, но БОЛЬШИМИ БУКВАМИ:
СОРТИРОВАТЬ =Н А Д О= ПО НЕСКОЛЬКИМ СТОЛБЦАМ. ЕЩЕ РАЗ: =ПО Н Е С К О Л Ь К И М=
создание дополнительного столбца приводит к необходимости его заполнения перед сортировкой.
Специально для Вас =персональный= вопрос:
КАКИМ ОБРАЗОМ МНЕ ЗАПОЛНИТЬ НОВЫЙ СТОЛБЕЦ, ЕСЛИ ЗАПОЛНИТЬ ЕГО НАДО ТАК ЧТОБЫ СОРТИРОВКА ПРОИЗВОДИЛАСЬ С УЧЕТОМ ДАННЫХ, РАСПОЛОЖЕННЫХ В ТРЕХ СТОЛБЦАХ.
Всем - сорри за капс. Надеюсь в дальнейшем на ответы по существу.
Номер ответа: 3
Автор ответа:
AKE
Вопросов: 0
Ответов: 7
Профиль | | #3
Добавлено: 27.10.06 00:25
Не обижайтесь, но действительно непонятно, что должно произойти (или не произойти)при изменении фамилии или адреса. Если человек должен остаться в той же позиции где и был, то дополнительный столбец и будет являться уникальным, никогда не изменяемым идентификатором личности, присвоенным ей автоинкрементацией (генератором, триггером или др. в зависимости от СУБД)при внесении нового человека в БД.
Ответ на "специальный" вопрос: Новый столбец заполняется при INSERте новой записи автоматически согласно "...порядка отображения" известного(надеюсь) пока только Вам.
Номер ответа: 4
Автор ответа:
Marki
Вопросов: 42
Ответов: 94
Профиль | | #4
Добавлено: 27.10.06 00:44
еще раз постараюсь пояснить задачу на придуманном примере:
1) столбец 1 - город
2) столбец 2 - улица
3) столбец 3 - ФИО
4) столбцы, не участвующие в сортировке
Требуется группировка по городам (например по возрастанию), внутри каждого города - по улице, и уже внутри каждой улицы - по ФИО.
Человек может переезжать в другой город с сохранением своих ФИО и например на такую же улицу - но он уже должен "переместиться" в группу другого города, там его улица должна попасть в соответствии с порядком сортировки на требуемое место и соответственно его ФИО - так же внутри "группы улицы" (если такая уже есть и там кто-то записан) должны быть отсортированы.
Т.е. ЛЮБОЕ изменение данных в трех первых столбцах требует сортировки сначала по первому столбцу, затем НЕ нарушая эту сортировку - по следующему и т.д.
Если совсем оказалось неясно - АНАЛОГОМ является сортировка в Excel:
при выборе сортировки предлагается:
СНАЧАЛА СОРТИРУЕМ ПО СТОЛБЦУ ИКС, ЗАТЕМ ПО СТОЛБЦУ ИГРЕК И ЗАТЕМ ПО СТОЛБЦУ ЗЭТ.
Номер ответа: 5
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #5
Добавлено: 27.10.06 00:53
А что тебе мешает после изменения данных выполнить новый запрос к БД и вернуть уже отсортированный по твоим полям набор записей?
Или у тебя обязательным условием является сортировака средствами исключительно DataGridView?
Номер ответа: 6
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #6
Добавлено: 27.10.06 01:03
И еще... насколько я знаю, этот контрол имеет замечательный метод - DataGridView.Sort(IComparer) И все,что тебе надо сделать - это написать класс,реализующий интерфейс IComparer и передать его в качестве аргумента методу Sort контрола DataGridView.. и будет тебе щастье!!!
Таким образом ты можешь отсортировать хоть по 23-м столбцам.. потому что реализию сортировки ты будешь писать сам в этом классе...
Номер ответа: 7
Автор ответа:
Marki
Вопросов: 42
Ответов: 94
Профиль | | #7
Добавлено: 27.10.06 01:08
сделать хочется действительно именно без запроса к базе... т.к. возможна ситуация что данные вносятся именно в список, без записи в саму базу.
В отношении IComparer - гм... метод есть, посмотрел в помощи до обращения сюда, но не уловил его сути (((
Номер ответа: 8
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #8
Добавлено: 27.10.06 01:17
Суть проста.. Дело в том, что DataGridView не имеет ни малейшего представления о том, что за данные находятся в твоих столбцах, как ты хочешь их сортировать и в каком порядке. Критериев сортировки может быть туча.. Для этого и создается этот класс. В нем пищшешь реализацию единственного метода Comparer,который будет и будет сравнивать строки в твоем наборе данных.. вот собственно и все...
Номер ответа: 9
Автор ответа:
Marki
Вопросов: 42
Ответов: 94
Профиль | | #9
Добавлено: 27.10.06 01:37
вот это "все" я как раз пока и не догнал, в результате чего стал искать другие пути решения той же задачи.
Номер ответа: 10
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #10
Добавлено: 27.10.06 02:23
Нууу, блин.. дружище.. а ты не пробовал набрать в гугле DataGridView.Sort(IComparer)? Нет?
К твоему удивлению вывалиться туева хуча ссылок с деталями реализации этого класса..
Вот одна из них..
http://msdn2.microsoft.com/en-us/library/wstxtkxs.aspx
Номер ответа: 11
Автор ответа:
HACKER
Разработчик Offline Client
Вопросов: 236
Ответов: 8362
Профиль | | #11
Добавлено: 27.10.06 05:03
Помойму глупо сортировать программно если можно запросом вынуть данные.
Воопервых оно быстрее будет, без ошибок... а главное легче реализовывается...
Номер ответа: 12
Автор ответа:
Marki
Вопросов: 42
Ответов: 94
Профиль | | #12
Добавлено: 27.10.06 09:20
2 EROS - спасибо, ссылку посмотрю.
2 HACKER - сложно раговаривать с самим собой. Это я про себя и так, на всякий случай.
Номер ответа: 13
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #13
Добавлено: 27.10.06 18:14
HACKER, ну не скажи... на счет быстрее вопрос спорный.. поскольку обращение к БД принято считать очень ресурсоемким процессом, и дергать БД лишний раз не есть хороший тон в программировании.. Легче-да.. тут я с тобой согласен, хотя и реализация этого метода сложной не назовешь. Этот способ сортировки не имеет ничего общего с известными тебе способами сортировки методами "пузырька" и ему подобным. Его задача сравнить в этой ф-ии 2 строки X & Y и вернуть один из 3 результатов.. -1,0,1 - вот и все! Вся реализация займет 7-10 строчек кода. Никаких перестановок в массиве и прочих прелестей сортировки VB6. Зато гибкость и управляемость кода налицо.
Номер ответа: 14
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #14
Добавлено: 27.10.06 21:32
Вот что то от нефига делать, решил протестировать этот метод сортировки..
''' Test DataGridView.Sort(IComparer)
''' </summary>
''' <remarks>
''' Add to form:
''' - DataGridView (Name = DataGridView1)
''' - Button (Name = btnSort)
''' </remarks>
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
'// Заполняем DataGridView тестовыми данными
Dim arrayFamily() As String = New String() {"Иванов", _
"Петров", _
"Сидоров", _
"Козлов", _
"Смирнов", _
"Васильев"}
Dim arrayFirstName() As String = New String() {"Иван", _
"Николай", _
"Михаил", _
"Пётр", _
"Василий", _
"Вячеслав"}
Dim arrayLastName() As String = New String() {"Александрович", _
"Владимирович", _
"Федорович", _
"Семенович"}
With DataGridView1.Columns
.Add("columnNumber", "№ п/п"
.Add("columnFamily", "Фамилия"
.Add("columnFirstName", "Имя"
.Add("columnLastName", "Отчество"
End With
Dim Rnd As New Random
For Counter As Int32 = 1 To 1000 '// Rows count
'// Первое поле (№ строки) для контроля сортировки
 ataGridView1.Rows.Add(New String() {Counter.ToString, _
arrayFamily(Rnd.Next(0, arrayFamily.Length)), _
arrayFirstName(Rnd.Next(0, arrayFirstName.Length)), _
arrayLastName(Rnd.Next(0, arrayLastName.Length))})
Next
End Sub
Private Sub btnSort_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnSort.Click
Dim stopWatch As New Stopwatch
stopWatch.Start()
'// Сортируем данные по 3 полям
 ataGridView1.Sort(New RowComparer)
stopWatch.Stop()
'// Show result
MessageBox.Show(String.Format("Sorting result is {0} ms", stopWatch.Elapsed.TotalMilliseconds), _
"Test DataGridView.Sort(IComparer)", _
MessageBoxButtons.OK, _
MessageBoxIcon.Information)
End Sub
''' <summary>
''' Приватный класс для сортировки строк DataGridView
''' Реализуем интерфейс System.Collections.IComparer
''' </summary>
''' <remarks>Регистр не учитываем (IgnoreCase = True)</remarks>
Private Class RowComparer
Implements Collections.IComparer
Public Function Compare(ByVal x As Object, _
ByVal y As Object) As Integer _
Implements System.Collections.IComparer.Compare
Dim rowX As DataGridViewRow = TryCast(x, DataGridViewRow)
Dim rowY As DataGridViewRow = TryCast(y, DataGridViewRow)
Dim compareResult As Int32
'// Проверяем входные данные
If rowX Is Nothing OrElse _
rowY Is Nothing Then Throw New ArgumentNullException("X or Y Is Nothing..."
'// Сравниваем 2 фамилиии
compareResult = String.Compare( _
rowX.Cells(1).Value, _
rowY.Cells(1).Value, _
True) '// Игнорируем регистр
'// Если они равны, то сравниваем имена
If compareResult = 0 Then _
compareResult = String.Compare( _
rowX.Cells(2).Value, _
rowY.Cells(2).Value, _
True)
'// Если снова одинаковые, то сравниваем отчества
If compareResult = 0 Then _
compareResult = String.Compare( _
rowX.Cells(3).Value, _
rowY.Cells(3).Value, _
True)
'// Возвращаем результат вызова
Return compareResult
End Function
End Class
End Class
Результат на моей машине 16,0479 ms
Сортировка по 3 полям для 1000 строк.. по- моему вполне приемлемо. На БД не тестил, но думаю, что на небольших объемах данных результат не сильно будет отличаться...
Номер ответа: 15
Автор ответа:
HACKER
Разработчик Offline Client
Вопросов: 236
Ответов: 8362
Профиль | | #15
Добавлено: 28.10.06 01:58
Гы действительно х.з. с быстродействием, не тестил (хотя думаю уж точно не медленее)... но по поводу реализации...
Путь какой-то грид будет привязан как рекордсет... тогда вся сортировка седется к sql запросу:
DB.Execute ("SELECT * FRON table ORDER BY [Поле] ASC "...