Загрузка данных
По старым случаям фиксируем: **сертификат есть, но заполнение постформы не подтверждается ни экспортом, ни проверкой ссылки**. Частичные данные и номер сертификата не заменяют подтверждение формы. `formReceived=0` пока оставляем; эти случаи откладываем как расхождение со стороны МТС.
Теперь проверим письмо и повторный email.
**1. Письмо участнику `10632747`, мероприятие `15999`**
Ранее выборка была пустой, поэтому ищем отправления как по участнику, так и по его отчётам — это поможет обнаружить неправильный `kodMember` в отправлении.
```sql
USE myNewVasya;
SELECT @@SERVERNAME AS serverName, DB_NAME() AS databaseName;
-- Участник и его отчёты.
SELECT
m.kod AS kodMember,
m.kodMerop,
m.emMem,
m.participantId,
m.profileId,
r.kod AS kodReport,
r.emZayavka,
r.a1,
r.processingStatus
FROM dbo.dat_members AS m
LEFT JOIN dbo.sb_reports AS r ON r.kodMember = m.kod
WHERE m.kod = 10632747;
-- Отправления: по участнику ИЛИ по связанному отчёту.
SELECT
s.kod AS sendKod,
s.kodMember,
s.kodMerop,
s.kodReport,
s.tipFL,
s.toEmail,
s.sendEM,
s.pause,
s.srvsDT,
s.dtSend,
s.resultSend,
s.g_UID
FROM dbo.sb_send AS s
WHERE s.kodMember = 10632747
OR EXISTS (
SELECT 1
FROM dbo.sb_reports AS r
WHERE r.kod = s.kodReport
AND r.kodMember = 10632747
)
ORDER BY s.kod DESC;
-- Журнал демона и фактическое отправление.
SELECT
j.kod AS journalKod,
j.kind,
j.kodMember,
j.kodReport,
j.state,
j.createdAt,
j.appliedAt,
j.sentAt,
j.sendKod,
s.kod AS existingSendKod,
s.sendEM,
s.pause,
s.dtSend,
s.resultSend
FROM dbo.mts_daemon_mail_v12 AS j
LEFT JOIN dbo.sb_send AS s ON s.kod = j.sendKod
WHERE j.kodMember = 10632747
OR EXISTS (
SELECT 1
FROM dbo.sb_reports AS r
WHERE r.kod = j.kodReport
AND r.kodMember = 10632747
)
ORDER BY j.createdAt DESC;
```
Если отправлений снова нет, **нужна исходная строка аудита с `sendKod`**. Сам факт отправки не должен удалять строку из результата этого запроса. Пока не сбрасываем флаги и не создаём повторное письмо.
**2. Повторный email внутри мероприятия `15732`**
Сначала найдём все записи с повторяющимся email, включая различия регистра и пробелы по краям:
```sql
USE myNewVasya;
;WITH Members AS (
SELECT
m.kod,
m.kodMerop,
m.emMem,
m.participantId,
m.profileId,
m.beInOn,
m.timeInMerop,
LOWER(LTRIM(RTRIM(m.emMem))) AS normalizedEmail
FROM dbo.dat_members AS m
WHERE m.kodMerop = 15732
AND NULLIF(LTRIM(RTRIM(m.emMem)), N'') IS NOT NULL
),
Duplicates AS (
SELECT normalizedEmail, COUNT_BIG(*) AS memberRows
FROM Members
GROUP BY normalizedEmail
HAVING COUNT_BIG(*) > 1
)
SELECT
d.normalizedEmail,
d.memberRows,
m.kod AS kodMember,
m.emMem AS originalEmail,
m.participantId,
m.profileId,
m.beInOn,
m.timeInMerop
FROM Members AS m
JOIN Duplicates AS d
ON d.normalizedEmail = m.normalizedEmail
ORDER BY d.normalizedEmail, m.kod;
```
Затем посмотрим, какие отчёты и сертификаты связаны с этими участниками. Отдельные выборки не будут перемножать отчёты и сертификаты между собой:
```sql
IF OBJECT_ID('tempdb..#DuplicateMembers') IS NOT NULL
DROP TABLE #DuplicateMembers;
SELECT m.kod AS kodMember
INTO #DuplicateMembers
FROM dbo.dat_members AS m
WHERE m.kodMerop = 15732
AND NULLIF(LTRIM(RTRIM(m.emMem)), N'') IS NOT NULL
AND EXISTS (
SELECT 1
FROM dbo.dat_members AS other
WHERE other.kodMerop = m.kodMerop
AND other.kod <> m.kod
AND LOWER(LTRIM(RTRIM(other.emMem)))
= LOWER(LTRIM(RTRIM(m.emMem)))
);
SELECT
r.kod AS kodReport,
r.kodMember,
r.kodProject,
r.a1,
r.manFIO,
r.listenerCntInteger,
r.processingStatus,
r.correctionApplied,
r.mtsFormLink
FROM dbo.sb_reports AS r
JOIN #DuplicateMembers AS d ON d.kodMember = r.kodMember
ORDER BY r.kodMember, r.kod;
SELECT
c.kod AS certificateRow,
c.kodMember,
c.kodReport,
c.participantId,
c.mtsCertNumber,
c.manFIO,
c.formReceived,
c.firstSeenAt,
c.lastCheckAt
FROM dbo.dat_mts_certificates AS c
JOIN #DuplicateMembers AS d ON d.kodMember = c.kodMember
WHERE c.kodMerop = 15732
ORDER BY c.kodMember, c.kod;
DROP TABLE #DuplicateMembers;
```
Результат будем трактовать так:
| Совпадения | Что это может означать |
| ------------------------------------------------------------------- | ------------------------------------------------- |
| Один email, одинаковый непустой `participantId` | Возможное повторное создание локального участника |
| Один email, разные `participantId`, одинаковый непустой `profileId` | Несколько регистраций одного профиля |
| Один email, разные `profileId` | Разные профили используют общий адрес |
| Два участника связаны с одним номером сертификата | Нужно проверить привязку сертификата |
**По одному email записи не объединяем и время участия не суммируем.** Пришлите результаты этих блоков — они покажут, есть ли реальное дублирование обработки или только общий почтовый адрес.