|
|
|
| 3-й день кручу в голове никак не придумаю...
Попробую сформулировать вопрос, может решение придет.
есть набор значений (ну условно таблица) с полями
Val - тектовое 255
Org - Long
ID - Long
IDError - Integer (изначально равно 1 для всех записей)
Значения в поле VAL ОДНОЗНАЧНО повторяющиеся (именно по этому эти записи в набор и попали).
Задача для одинаковых VAL :
если есть запись с Org = 1 то
если во ВСЕХ других записях с этим VAL поле ID равен текущему, то IDError для этих = 2, а для текущей NULL
если встречаются другие ID, то для каждого встречающегося ID, первая запись (фактически любая, но одна) IDError = 1, а все остальные IDError = 2
если нез записи Org =1, то
для всех одинаковых ORG
если во ВСЕХ других записях с этим VAL поле ID равен текущему, то IDError для этих = 2, а для текущей NULL
если встречаются другие ID, то для каждого встречающегося ID, "первая" запись (фактически любая, но одна) IDError = 1, а все остальные IDError = 2
|
Попробую пояснить на примере
После обработки должно получиться:
VAL Org ID IDError
a 1 1 Null (т.к. ORG = 1, а все остальные ID одинаковые
a 4 1 2
a 5 1 2
b 1 1 1 (т.к. ORG = 1, а ID попадаются разные, то в итоге должен проставить IDError = 1
b 1 2 1 для одной записи в каждом ID, а в остальных IDError = 2)
b 2 1 2
b 2 1 2
b 3 5 1
c 2 1 NULL (т.е. нет записей с ORG = 1, а для каждого org значение id одинаковое, то для "первого" idError = null
c 2 1 2 (для остальных idError = 2)
c 3 2 NULL
c 3 2 2
c 4 3 NULL
d 2 1 1 (Org <>1. для ORG есть разные ID, то для каждого ORG и каждого ID, для "первой" записи IDError = 1, для остальных
d 2 1 2 IDError = 2
d 2 2 1
d 2 3 1
d 2 3 2
d 3 1 NULL (т.к. для ORG = 3 все ID одинаковые, то для "первой" записи IDError = Null для остальных IDError = 2
d 3 1 2
d 3 1 2
d 3 1 2
|
| |
|
| |
|
35 Кб. |
|
| Вот пример данных | |
|
| |
|
|
|
| Может как то примерно так?
Качество кода и скорость пока не рассматриваем.
Там где .Fields(3) = 1 можно не обновляться, но я для наглядности сначала обновил в таблице все на 0, а то не видно было, где я писал, а где так и было.
Добавлено: похоже орг упустил | |
|
| |
|
|
|
| скорость тут вообще фигня вопрос, по оценкам это будет 2-3% от обрабатываемого кол-ва (т.е. 1000-1500 записей)
Кручу 2 идеи
1. Использовать SHAPE .. пока не до конца понял как можно приспособить
2. банальный Dcount или рекордсеты с условием
взял запись, проверил наличие Org =1, если есть, то проверил наличие разных ID, если есть взял записи для каждого ID ... ну и т.д.
Спасибо, код вечерком посмотрю | |
|
| |
|
|
|
| Этот вроде правильнее с точки зрения алгоритма:
Public Function UpdateErr()
Dim oldVal As String
Dim oldOrg As Long
Dim oldID As Long
Dim varBookmarkS As Variant
Dim flgID As Boolean
Dim strID As String
With CurrentDb.OpenRecordset("SELECT Val, Org, ID, IDError FROM Исходная ORDER BY Val, Org, ID")
Do Until .EOF
flgID = True
oldVal = .Fields(0)
oldID = .Fields(2)
If .Fields(1) = 1 Then
varBookmarkS = .Bookmark
Do While oldVal = .Fields(0) And flgID
flgID = flgID And oldID = .Fields(2)
.MoveNext
If .EOF Then Exit Do
Loop
.Bookmark = varBookmarkS
If flgID Then
.Edit
.Fields(3) = Null
.Update
.MoveNext
Do While oldVal = .Fields(0)
.Edit
.Fields(3) = 2
.Update
.MoveNext
If .EOF Then Exit Do
Loop
Else
oldID = .Fields(2)
strID = CStr(oldID) & ";"
.Edit
.Fields(3) = 1
.Update
.MoveNext
Do While oldVal = .Fields(0)
.Edit
If UBound(Filter(Split(strID, ";"), CStr(.Fields(2)), True)) > -1 Then
.Fields(3) = 2
Else
.Fields(3) = 1
oldID = .Fields(2)
strID = strID & CStr(oldID) & ";"
End If
.Update
.MoveNext
If .EOF Then Exit Do
Loop
End If
Else
Do While oldVal = .Fields(0)
oldOrg = .Fields(1)
flgID = True
oldID = .Fields(2)
varBookmarkS = .Bookmark
Do While oldVal = .Fields(0) And oldOrg = .Fields(1) And flgID
flgID = flgID And oldID = .Fields(2)
.MoveNext
If .EOF Then Exit Do
Loop
.Bookmark = varBookmarkS
If flgID Then
.Edit
.Fields(3) = Null
.Update
.MoveNext
Do While oldVal = .Fields(0) And oldOrg = .Fields(1)
.Edit
.Fields(3) = 2
.Update
.MoveNext
If .EOF Then Exit Do
Loop
Else
oldID = .Fields(2)
.Edit
.Fields(3) = 1
.Update
.MoveNext
Do While oldVal = .Fields(0) And oldOrg = .Fields(1)
.Edit
If oldID = .Fields(2) Then
.Fields(3) = 2
Else
.Fields(3) = 1
oldID = .Fields(2)
End If
.Update
.MoveNext
If .EOF Then Exit Do
Loop
End If
If .EOF Then Exit Do
Loop
End If
Loop
.Close
End With
End Function
|
| |
|
| |
|
|
|
|
| SELECT Исходная.Val, (SELECT Max(T1.Org) AS [Max-Org]
FROM Исходная AS T1
WHERE (((T1.Val)=Исходная.Val) AND ((T1.Org)=1))) AS IsOrg1, Исходная.Org, Min(Исходная.ID) AS MinID, Max(Исходная.ID) AS MaxID
FROM Исходная
GROUP BY Исходная.Val, Исходная.Org;
Этот запрос группирует по Val и Org, показывает Min ID и Masx ID, а также для каждого Val возвращает признак наличия Org=1 (IsOrg1 возвращакт 1 или Null). В каждой записи достаточно информации, чтоб после простой логики определить значение IDError и выполнить запрос на обновление записей.
Например для записи:
Val IsOrg1 Org MinID MaxID
tir nbs lrrs 14 12000078 12000285
|
Org<>1 (14), нет записей с этим Val и Org=1 (IsOrg1=Null) и есть записи с разными индексами (12000078 <> 12000285), то в записях с этим Val, Org и ID = MinID (первая запись) меняем IDError на Null, а для ID <> MinID - на 2. Т.е. запрос типа:
UPDATE Исходная SET Исходная.IDError = IIf([Исходная]![ID]=12000078,Null,2)
WHERE (((Исходная.Val)='tir nbs lrrs') AND ((Исходная.Org)=14));
ИМХО, 926 операций обновления (столько возвращает запрос) быстрее, чем 1732 (записей в таблице). | |
|
| |
|
|
|
| Сильно!
Снимаю шляпу! | |
|
| |