powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Поиск пропущенных интервалов (2 поля)
25 сообщений из 27, страница 1 из 2
Поиск пропущенных интервалов (2 поля)
    #39081695
Diminicandum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте, господа.

Помогите пожалуйста.
Есть таблица интервалов (приложение), где BHID - номер выборки, FROM - значение начала интервала выборки, TO - значения конца интервала выборки, NS - номер интервала.
Нужно запросом отобразить пропущенные интервалы, например: для BHID=1 пропущенный интервал 8-10, для BHID=2 пропущенный интервал 10-12.


Пока получилось только рассчитать в какой выборке есть пропуск:

1. Запрос [2_12_011_Ancillary]:
SELECT ASSAY.BHID, Sum([to]-[from]) AS SumLen, Max(ASSAY.TO) AS MaxTO, Min(ASSAY.FROM) AS [Min-FROM], Count(ASSAY.NS) AS [Count-NS]
FROM ASSAY
GROUP BY ASSAY.BHID
HAVING (((ASSAY.BHID)<>""));

2. Запрос [Пропуски и перехлёсты]:
SELECT [2_12_011_Ancillary].BHID, [2_12_011_Ancillary].SumLen, [2_12_011_Ancillary].MaxTO, Abs([SumLen]-[MaxTO]) AS Div, IIf([SumLen]-[MaxTO]>0,"Перехлест","Пропуск") AS [Возможная ошибка]
FROM 2_12_011_Ancillary
WHERE (((Abs([SumLen]-[MaxTO]))>0.01));
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39081710
Diminicandum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть еще вариант, но он не устраивает, т.к. отображает только соседние интервалы от пропущенного:

1. Запрос [2_12_011_Ancillary]:
SELECT ASSAY.BHID, Sum([to]-[from]) AS SumLen, Max(ASSAY.TO) AS MaxTO, Min(ASSAY.FROM) AS [Min-FROM], Count(ASSAY.NS) AS [Count-NS]
FROM ASSAY
GROUP BY ASSAY.BHID
HAVING (((ASSAY.BHID)<>""));


2. Запрос [2_12_01_Пропуски]:
SELECT [2_12_011_Ancillary].BHID, [2_12_011_Ancillary].SumLen, [2_12_011_Ancillary].MaxTO, Abs([SumLen]-[MaxTO]) AS Div, IIf([SumLen]-[MaxTO]>0,"Перехлест","Пропуск") AS [Возможная ошибка]
FROM 2_12_011_Ancillary
WHERE (((Abs([SumLen]-[MaxTO]))>0.01));

3. Запрос [Пропуски]:
SELECT [2_12_01_Пропуски].BHID AS Выражение1, [2_12_01_Пропуски].F1 AS [FROM], [2_12_01_Пропуски].T1 AS [TO]
FROM 2_12_01_Пропуски
WHERE ((([2_12_01_Пропуски].X)<>2));
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39081735
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пронумеруйте интервалы в группе с равными [BHID] (скажем, по возрастанию FROM), а затем выберите пары, у которых номер различается на 1, а [TO] меньшего не равно [FROM] большего.
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39081785
Diminicandum, потестируйте такой вариант
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
SELECT Q1.BHID, Q1.[TO] As _FROM, Min(Q2.[FROM]) As _TO 
FROM
(SELECT A1.BHID, A1.[TO]
FROM ASSAY As A1 INNER JOIN ASSAY AS A2 ON A1.BHID=A2.BHID And A1.[TO] <= A2.[FROM]
GROUP BY A1.BHID, A1.[TO]
HAVING Min(A2.[FROM])<>A1.[TO]) As Q1
INNER JOIN
(SELECT A1.BHID, A1.[FROM]
FROM ASSAY As A1 INNER JOIN ASSAY AS A2 ON A1.BHID=A2.BHID And A1.[FROM] >= A2.[TO]
GROUP BY A1.BHID, A1.[FROM]
HAVING Max(A2.[TO])<>A1.[FROM]) As Q2
ON Q1.BHID=Q2.BHID And Q1.[TO]<=Q2.[FROM]
GROUP BY Q1.BHID, Q1.[TO]
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082113
Diminicandum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina, спасибо за ответ. К сожалению с Access только начал знакомство, не знаю как пронумировать интервалы, единственное что приходит в голову: "ID1:[BHID]&"-"&[NS]". Подскажите пожалуйста, как задать последовательную нумерацию отсортированных проб?
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082119
Diminicandum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-Практикант-, спасибо огромное! Работает!
Правда совсем не похоже на знакомые мне "запросы" Access. Посоветуйте пожалуйста книги по SQL, желательно для "чайников"? С чего начать?
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082121
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DiminicandumС чего начать?
Порекомендую бесплатные онлайн-курсы на intuit.ru по основам SQL.
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082123
Diminicandum, а почему это надо делать именно запросом?
Я бы в процедуре открыл Recordset, отсортированный по BHID и FROM, в цикле для каждого BHID сравнивал FROM текущей с TO предыдущей и вылавливал пропущенные.
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082130
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Diminicandumне знаю как пронумировать интервалы
Посмотрите тему Автонумерация записей внутри группы (ногами не бить) :) . Рекомендую использовать метод 2 (с использованием DCount), он наиболее прост для понимания и адаптации.
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082236
ROI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Анатолий ( Киев )Diminicandum, а почему это надо делать именно запросом?
Я бы в процедуре открыл Recordset, отсортированный по BHID и FROM, в цикле для каждого BHID сравнивал FROM текущей с TO предыдущей и вылавливал пропущенные.
Я понял, тут извращенсы-им нравится все на SQL, а то что он для многих вещей не предназначен, это их не интересует вся фишка, что на SQL портянке величиной А4.
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082282
Rivkin Dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ROIАнатолий ( Киев )Diminicandum, а почему это надо делать именно запросом?
Я бы в процедуре открыл Recordset, отсортированный по BHID и FROM, в цикле для каждого BHID сравнивал FROM текущей с TO предыдущей и вылавливал пропущенные.
Я понял, тут извращенсы-им нравится все на SQL, а то что он для многих вещей не предназначен, это их не интересует вся фишка, что на SQL портянке величиной А4.
А я уверен, что делатьтакие вещи в рекордсете - как раз и есть извращение! SQL как раз и предназначен для таких вещей и вменьшей мере в курсорах и рекордсетах! В аксе, конечно, труднее такие вещи делаются, но, пожалуйста, -Практикант- , хоть и не оптимальным способом, но показал как это сделать. Akina на пальцах рассказал как это сделать. Ничего сложного. Только понять. А как будем писать в рекордсете? И куда и как выводить результат? При достаточно большом объеме данных, уверен, селект отработает значительно быстрее.

ЗЫ
Я уж не говорю о SQL Server, где сейчас счетчик длается мгновенно
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082306
ROI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Rivkin Dmitryуж не говорю о SQL Server, где сейчас счетчик длается мгновенно
Вы заблуждаетесь.
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082334
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ROI , открывать рекордсет и волочь все данные на клиента для обработки, которую можно выполнить на сервере, чтобы потом принять только готовый результат - вот это и есть извращение.
Правда, таких извращенцев очень трудно лечить - нужны сильные средства, типа канала до сервера через EDGE или там платно-помегабайтного трафика.
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082374
Rivkin Dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ROIRivkin Dmitryуж не говорю о SQL Server, где сейчас счетчик длается мгновенно
Вы заблуждаетесь.
Ну, что-же, предлагаю предъявить код.

Вот так я вижу решение в аксе:
1 этап - создаем сохраняемый запрос tmp:

Код: sql
1.
2.
select (select count(*) + 1 from ASSAY where BHID = t.BHID and [FROM] < t.[FROM]) as id, t.*
from ASSAY as t



2 этап - сабственно запрос с участием двух сохраненных:

Код: sql
1.
2.
3.
4.
5.
6.
select t1.BHID, t1.[TO], t2.[FROM], iif(t1.[TO] < t2.[FROM], 'Пропуск', 'Перехлест') as Note
from tmp as t1
inner join tmp as t2
on t1.BHID = t2.BHID
	and t1.id + 1 = t2.id
where t1.[TO] <> t2.[FROM]


Все

В терминах SQL Server:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
;
with
tmp as (
	select row_number() over (order by BHID, [FROM]) as id, *
	from ASSAY
)
	
select t1.BHID, t1.[TO], t2.[FROM], case when t1.[TO] < t2.[FROM] then 'Пропуск' else 'Перехлест' end as Note
from tmp as t1
inner join tmp as t2
on t1.BHID = t2.BHID
	and t1.id + 1 = t2.id
where t1.[TO] <> t2.[FROM]



Предлагаю вам привести код обработки в рекордсете, а автора топика произвести испытания и рассудить нас
Желательно, конечно, на таблице, содержащей побольше записей
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082376
Rivkin Dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akina ROI , открывать рекордсет и волочь все данные на клиента для обработки, которую можно выполнить на сервере, чтобы потом принять только готовый результат - вот это и есть извращение.
Правда, таких извращенцев очень трудно лечить - нужны сильные средства, типа канала до сервера через EDGE или там платно-помегабайтного трафика.
+1
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082377
ROI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akina ROI , открывать рекордсет и волочь все данные на клиента для обработки, которую можно выполнить на сервере, чтобы потом принять только готовый результат - вот это и есть извращение.
Правда, таких извращенцев очень трудно лечить - нужны сильные средства, типа канала до сервера через EDGE или там платно-помегабайтного трафика.
Я говорил про портянки А4 на SQL.
Еще вопрос в чем (открывать рекордсет и волочь все данные на клиента) или портянка величиной А4 на SQL.
Если учесть что форум по "Access"
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082384
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ROIЯ говорил про портянки А4 на SQL.
А какая разница, сколько строк в коде, если он правилен и эффективен?
Кстати, SQL-запрос вполне можно записать в ОДНУ строку, а при печати уменьшить шрифт и уложиться в ма-а-аленький квадратик.

ROIЕсли учесть что форум по "Access"
Как раз сентенции про SQL-портянки делают обсуждение идеологическим и выводят за рамки отдельно взятой СУБД.
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082394
ROI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaА какая разница, сколько строк в коде, если он правилен и эффективен?
Кстати, SQL-запрос вполне можно записать в ОДНУ строку, а при печати уменьшить шрифт и уложиться в ма-а-аленький квадратик.
Разнинца огромная 90% пишущего на наш форум вообще не имеют понятия о RecordSet, а у ж тем более о синтаксисе SQL.

AkinaROI
Как раз сентенции про SQL-портянки делают обсуждение идеологическим и выводят за рамки отдельно взятой СУБД.
Естественно, они основ не знают а вым им SQL в зубы
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082450
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ROI90% пишущего на наш форум вообще не имеют понятия о RecordSet
А оно им зачем? ну так... мастера есть, визуальная рихтовка форм/отчётов есть, и этими инструментами накрывается 90% надобностей пишущего тут народа. Более того, визуальное построение запроса зачастую и проще, и быстрее, чем пальцы ломать - а заодно, что приятно, построитель не ошибается в синтаксисе. Можно вообще и слова такого не знать - SQL,- и тем не менее создать достаточно объёмное и функциональное приложение - и я видел такие.
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082467
ROI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akinaмастера есть, визуальная рихтовка форм/отчётов есть, и этими инструментами накрывается 90% надобностей пишущего тут народа. Более того, визуальное построение запроса зачастую и проще, и быстрее, чем пальцы ломать - а
Это когда такое помогало в том то и дело, что они мастерами не могут,
а уж в ручную как вы говорите "рихтовать".
Вы очень наивны.
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082482
Фотография ПЕНСИОНЕРКА
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Diminicandum,

я бы видимо для ясности в понимании решала задачу процедурой
видимо сюда бы добавила проверку на наложение интервалов

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
Sub a151021()
Dim rst As DAO.Recordset, s1
s1 = ""
s1 = s1 & "select BHID ,[from] ,[to] "
s1 = s1 & " from assay t1 order by BHID ,[from] ,[to]"
Set rst = CurrentDb.OpenRecordset(s1)
Do While rst.EOF = False
z1 = -1         ''начальное значение конца интервала
g1 = rst!BHID   ''запоминание группы
    Do While rst.EOF = False
        If rst!BHID > g1 Then  ''смена группы
        Exit Do
        End If
        If z1 = -1 Then z1 = rst![from]
        If z1 < rst![from] Then
        Debug.Print g1, "нет интервала ("; z1; "-"; rst![from]; ")"
        End If
        z1 = rst![to]  ''запоминание значения конца интервала
        rst.MoveNext
    Loop
Loop
rst.Close
Set rst = Nothing


End Sub
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39082490
Фотография __Michelle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ROI...90% пишущего на наш форум вообще не имеют понятия о RecordSet, а у ж тем более о синтаксисе SQL.Это откуда такие данные про 90%?
С потолка?
Хоть один аргумент убедительный приведите.
ROIЕстественно, они основ не знают а вым им SQL в зубыА что, SQL такой прям бином Ньютона?)))
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39084142
Решил не ждать милостей от природы :) и сравнить свой запрос 18304646 с запросом Akina-Rivkin 18307428 . Заодно до кучи и процедуру, определяющую пропущенные интервалы и помещающую результаты в таблицу tabSkip, прилепил (см. текст ниже,в спойлере).
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
Sub asskip()
Dim DB As DAO.Database, RSA As DAO.Recordset, RSW As DAO.Recordset
Dim b$, t&
  Set DB = CurrentDb
  DB.Execute "DELETE * FROM tabSkip"
  Set RSA = DB.OpenRecordset("SELECT * FROM Assay ORDER BY BHID, [FROM]", dbOpenSnapshot)
  Set RSW = DB.OpenRecordset("tabSkip", dbOpenDynaset)
  If Not RSA.EOF Then b = RSA!BHID - 1
  Do Until RSA.EOF
    If b = RSA!BHID Then
      If RSA!FROM > t Then
        RSW.AddNew
        RSW!BHID = b: RSW!FROM = t: RSW!To = RSA!FROM
        RSW.Update
      End If
    Else
      b = RSA!BHID
    End If
    t = RSA!To
    RSA.MoveNext
  Loop
  RSA.Close: Set RSA = Nothing
  RSW.Close: Set RSW = Nothing
  Set DB = Nothing
End Sub


Результаты тестирования приведены ниже и получены при 100 000 записей исходной таблицы ASSAY, которая кроме того имела составной индекс по полям BHID и FROM. Время работы участников теста приведено в секундах.

ПробаПроцедура-Практикант-Akina-Rivkin10.656253.85937522.2656320.68753.85937521.7343830.656253.89062522.54688
Следует отметить, что отсутствие индекса слабо влияло на работу процедуры и запроса -Практикант-, а вот запрос Akina-Rivkin становился ну очень тормознутым. Даже на объеме 10 000 записей время его работы превысило 50 минут (больше не хватило терпения ждать и вырубил его). Немного улучшился показатель (~21 мин.) при замене в запросе tmp подзапроса с Count на функцию DCount.
На всякий случай
Процедура заполнения исходной таблицы ASSAY
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Sub AddAssay()
Dim i&, j&, ar
  ar = Array(0, 5, 5, 6, 6, 8, 10, 15, 15, 20, 25, 30, 30, 36, 36, 40, 42, 45, 45, 50)
  CurrentDb.Execute "DELETE * FROM ASSAY"
  With CurrentDb.OpenRecordset("assay", dbOpenDynaset)
  For i = 1 To 10000
    For j = 0 To 19 Step 2
      .AddNew: !BHID = i: !FROM = ar(j): !To = ar(j + 1): .Update
    Next
  Next
  End With
End Sub


Процедура тестирования
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
Sub timtest()
Dim t!, sq$
  t = Timer
  asskip
  Debug.Print "Процедура", Timer - t
  
'-----------------------------------------------------------
  
  sq = "SELECT Q1.BHID, Q1.[TO] As _FROM, Min(Q2.[FROM]) As _TO " & _
       "FROM " & _
       "(SELECT A1.BHID, A1.[TO] " & _
       "FROM ASSAY As A1 INNER JOIN ASSAY AS A2 ON A1.BHID=A2.BHID And A1.[TO] <= A2.[FROM] " & _
       "GROUP BY A1.BHID, A1.[TO] " & _
       "HAVING Min(A2.[FROM])<>A1.[TO]) As Q1 "
  sq = sq & "INNER JOIN " & _
      "(SELECT A1.BHID, A1.[FROM] " & _
      "FROM ASSAY As A1 INNER JOIN ASSAY AS A2 ON A1.BHID=A2.BHID And A1.[FROM] >= A2.[TO] " & _
      "GROUP BY A1.BHID, A1.[FROM] " & _
      "HAVING Max(A2.[TO])<>A1.[FROM]) As Q2 " & _
      "ON Q1.BHID=Q2.BHID And Q1.[TO]<=Q2.[FROM] " & _
      "GROUP BY Q1.BHID, Q1.[TO]"
  t = Timer
  CurrentDb.OpenRecordset(sq).MoveLast
  Debug.Print "-Практикант-", Timer - t
  
'-----------------------------------------------------------

  sq = "select t1.BHID, t1.[TO], t2.[FROM], iif(t1.[TO] < t2.[FROM], 'Пропуск', 'Перехлест') as Note_ " & _
       "from tmp as t1 " & _
       "inner join tmp as t2 " & _
       "on t1.BHID = t2.BHID " & _
       "  and t1.id + 1 = t2.id " & _
       "where t1.[TO] <> t2.[FROM]"
  t = Timer
  CurrentDb.OpenRecordset(sq).MoveLast
  Debug.Print "Akina-Rivkin", Timer - t
End Sub

...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39084171
Mina Anna Mazzini
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-Практикант-... а вот запрос Akina-Rivkin становился ну очень тормознутым. Даже на объеме 10 000 записей время его работы превысило 50 минут... Отчаянные люди...
А как же я ворочаю базы по 3+ мио записей с производительностью на E6750 4G, к примеру, от 10 до 30 тыс. записей в секунду?
...
Рейтинг: 0 / 0
Поиск пропущенных интервалов (2 поля)
    #39085769
Rivkin Dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-Практикант-,
Вынужден признать, что в аксе рекордсет оказался шустрее запроса. Хотя я и остаюсь убежденным сторонником работы с запросами, чем с рекордсетами. Пока объяснения результатам проверки я не нашел. Даже при уточнении проверки - после отработки процедуры следует открыть результат запроса в рекордсете, так-же, как и результат твоего запроса. Свою процедуру я изменил незначителтно: вместо запроса tmp я создаю и заполняю таблицу с таким же именем. Количество записей в исходной таблице я увеличил на порядок. В результате получил
timtest
Proc 18.78125
Pract 68.89453
Akina-Rivkin 53.09375

Т.е. запросы оказались медленее процедуры в 3-4 раза. Странно. Предполагаю, что сей эффект верен только для локальной БД, когда не надо тащить данные по сети. Попробую сделать проверку в сети. Доложусь
...
Рейтинг: 0 / 0
25 сообщений из 27, страница 1 из 2
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Поиск пропущенных интервалов (2 поля)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]