Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > SQL, базы данных
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.02.2023, 20:45   #1
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 525
По умолчанию Сначало группировка, потом объединение

Доброе время суток,

У меня есть таблица EQUIPMENT (оборудование) и CERTIFICATE (сертификаты) к этому оборудованию (каждое оборудование имеет несколько сертификатов)
Имелся также и рабочий запрос (до некоторого времени) для выборки просроченных сертификатов, который выводит на экран список оборудования и один сертификат к каждому оборудованию, если в таблице CERTIFICATE поле DISPLAY = 1 (1-это отображение, 0 – скрытие сертификата)

Код:
Select eq.ID, eq.NAME,  eq.CONTROL_MIN_DATE, eq."TYPE", eq.NUMBER, ….
 u.FULL_NAME as u_EQUIPMENT_USER, ld.NAME_SHORT as l_LABORATORY_DOC, ud.FULL_NAME as u_USER_DOC,
 (case when c.NUMBER_CERT = '-1' then '' else c.NUMBER_CERT end) as c_NUMBER_CERT,  c.DATE_OPERATION as c_DATE_OPERATION, c.CALIBRATION_INTERVAL as c_CALIBRATION_INTERVAL
 from EQUIPMENT eq
 left join LABORATORY l on l.id = eq.EQUIPMENT_LABORATORY_ID
 left join LABORATORY ld on ld.id = eq.LABORATORY_DOC_ID
 left join CERTIFICATE c on c.DEVICE_ID_CL = eq.ID and c.DISPLAY = 1
  left join USERS_DATA u on u.ID = eq.EQUIPMENT_PARENT_USER_ID
  left join USERS_DATA ud on ud.ID = eq.USER_DOC_ID
    where eq.ARCHIVE in (1)
  and (((eq.CONTROL_MIN_DATE < '02.02.2023' and not eq.CONTROL_MIN_DATE is null)  or (eq.CONTROL_MIN_DATE is null and eq.COUNT_CERT <> -1)  or (eq.CONTROL_MIN_DATE is null and eq.COUNT_CERT >= 0)  or (eq.COUNT_CERT_REQUIRE <> eq.COUNT_CERT))
  and ((eq.CONTROL_MIN_DATE < '02.02.2023' and not eq.CONTROL_MIN_DATE is null)  or (eq.CONTROL_MIN_DATE is null and eq.COUNT_CERT <> -1)  or (eq.CONTROL_MIN_DATE is null and eq.COUNT_CERT >= 0)  or (eq.COUNT_CERT_REQUIRE <> eq.COUNT_CERT)))

and ((c.CONTROL = 1 and eq.PASSPORT = 0) or ((c.CONTROL is null or c.CONTROL=1) and eq.PASSPORT = 1))

  order by eq.EQUIPMENT_PARENT_USER_ID, eq.NAME, eq.TYPE, eq.NUMBER, eq.NEMBER_INVENTORY
Этот запрос оказался НЕ верен, из него нужно убрать c.DISPLAY = 1 - а без этого параметра, в результате, появятся дубли оборудования
каждый сертификат имеет дату окончания, и статус актуализации CONTROL = 1 (1- серитификат актуален, 0 - сертификат не актуален)

Зарос работал до некоторого времени, пока пользователь выставлял c.DISPLAY = 1, т.е. отбражать один из сертификатов в окне оборудования. (проблема появилась, когда сертификаты можно скрывать - не выводить на экран, но по ним всеравно есть контроль (CONTROL = 1)) И это мне помогало избавится от отображения дублей оборудования, т.к. могут быть несколько просроченных сертификатов у одного оборудования.

Вопрос:
можно ли до операции JOIN в выше указанном запросе, выбрать из таблицы CERTIFICATE по одному просроченному сертификату для каждого оборудования, и обязательно вывести на экран, даже если DISPLAY = 0.
На рис. показано часть таблицы сертификатов относящиеся к двум оборудованием (с ID = 103 и 221) связка с табл. EQUIPMENT по полю DEVICE_ID_CL,
Т.е. я хочу делать по этой таблице группировку по полю DEVICE_ID_CL с таким расчетом, что результатом должна быть строка с ID=951 (в которой DISPLAY = 1), а если в группе только DISPLAY = 0, то вывести сертификат с максимальным ID, т.е. 835 исходя из рисунка
У меня группировка выходит только всегда с максимальным ID,

т.е. как выбрать строку с ID = 951 - не выходит

Заранее спасибо
Изображения
Тип файла: png 1234.png (4.1 Кб, 24 просмотров)

Последний раз редактировалось KBO; 06.02.2023 в 17:34.
KBO вне форума Ответить с цитированием
Старый 06.02.2023, 09:25   #2
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Код:
select top 1 max(id), device, display
from ...
group by device, display
order by display desc
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 06.02.2023 в 09:29.
evg_m вне форума Ответить с цитированием
Старый 06.02.2023, 15:42   #3
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 525
По умолчанию

Код не очень подошел...
- я использую FireBird 3.0 и там "top" - нет, вместо него взял "first" (если я вас правильно понял)
- может я не правильно выразился, извиняюсь, но исходя из картинки результатом запроса должны быть строки с ID: 835 и 951 (максимум я и сам могу найти каждой группы) )

Разъяснение:
- в кажой группе "DEVICE_ID_CL", может существовать только одна строка с c."DISPLAY"=1 (остальные строки в группе с значением "0"), а могут быть все с "0" в группе (т.е. с каждой группы сертификатов принадлежащих одному оборудованию, на экран выводится только один сертификат)
- выбираем строки с значением c.CONTROL=1 - обязателен для каждой группы
- если в группе строка с c."DISPLAY"=1 и c.CONTROL=1 - выводим эту строку (она может быть не с максимальным ID в группе)
- если в группе c."DISPLAY"=0 (во всех строках группы), то выводим строку с c.CONTROL=1 - и с максимальным ID в группе

Последний раз редактировалось KBO; 06.02.2023 в 17:13.
KBO вне форума Ответить с цитированием
Старый 06.02.2023, 16:42   #4
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
(она может быть не с максимальным ID в группе)
max(id) --- считается для КАЖДОЙ группы независимо
, device, display

Цитата:
может существовать только одна строка с c."DISPLAY"=1
максимум для ОДНОЙ строки просто равен данной сроке

Цитата:
выбираем строки с значением c.CONTROL=1 - обязателен для каждой группы
Код:
where control =1
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 06.02.2023, 17:04   #5
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 525
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
max(id) --- считается для КАЖДОЙ группы независимо
, device, display
да, независимо, - оно считается только для тех(той) групп(ы), в которой c."DISPLAY"=0 (во всех строках каждой группы) (для всех остальных групп, это группы там где есть DISPLAY=1 и CONTROL=1 - берется просто ID)

Цитата:
Сообщение от evg_m Посмотреть сообщение
where control =1
ага

Цитата:
Сообщение от evg_m Посмотреть сообщение
максимум для ОДНОЙ строки просто равен данной сроке
да (у каждой строки, может быть 0 или 1)

P.S.
Я чуть рисунок дополнил..., но результат остаётся тем же, ID: 835 и 951

Последний раз редактировалось KBO; 06.02.2023 в 17:37.
KBO вне форума Ответить с цитированием
Старый 06.02.2023, 20:03   #6
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Код:
select device, 
gr0.id, gr1.id, -- просто на всякий случай 
case when gr1.id is null then gr0.id else gr1.id end as mixid --и вычисляем нужное значение
from ( select max(id) as id, device
          from  ...
          where control =1 
                                   and display =0  --возможно из без этого
          group by device
        ) gr0
left join (select id, device
             from ...
             where control =1 and display =1
           ) gr1 on gr0.device =gr1.device
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 06.02.2023 в 20:07.
evg_m вне форума Ответить с цитированием
Старый 07.02.2023, 00:44   #7
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 525
По умолчанию

Спасибо!!! интересный алгоритм...

а я вчера думал про "merge" (как у вас, сначало выборка с DISPLAY = "0", потом с "1", а потом слить их по "DEVICE_ID_CL")

Последний раз редактировалось KBO; 07.02.2023 в 00:47.
KBO вне форума Ответить с цитированием
Старый 07.02.2023, 01:42   #8
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 525
По умолчанию

Единственное что, мне кажется тут нужно не join применять, т.к. группировка по DEVICE - их нельзя сравнинвать, потому что это разные группы DEVICE, в одном случае в группе DISPLAY=0, в другом в группе - DISPLAY=1 - просто не будет объединения... а будут исключения

Результаты этих запросов получается нужно сложить. Скорее всего union необходим, чтоб собрать все DEVICE

Последний раз редактировалось KBO; 07.02.2023 в 02:03.
KBO вне форума Ответить с цитированием
Старый 07.02.2023, 09:16   #9
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
чтоб собрать все DEVICE
Код:
          where control =1 
                                   and display =0  --возможно из без этого
          group by device  --мы УЖЕ получили все возможные device
Код:
left join ( ...   where control =1 and display =1) gr1 on gr0.device =gr1.device
ДОПОЛНИТЬ все строки данными о тех же device но c display =1 ( если возможно)
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 07.02.2023 в 09:26.
evg_m вне форума Ответить с цитированием
Старый 07.02.2023, 13:32   #10
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 525
По умолчанию

Сейчас буду разбираться.

Я ошибся с union

Последний раз редактировалось KBO; 07.02.2023 в 14:37.
KBO вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
ввожу сначало 10 цифр по порядку и заполняю массив потом он сортируется и после стоит цикл вывода этих отсортированных чисел ROMAN_ShARP C# (си шарп) 4 05.03.2020 08:27
DBLookupComboBox и join –значения сначало пропадают, потом появляются KBO Помощь студентам 0 13.11.2018 02:00
Группировка значений по критерию и их объединение и запись в строку kwns Microsoft Office Excel 1 28.06.2018 23:37
Синтаксическое дерево (парсер) - сначала раскрываем модуль, потом перетаскиваем известное и неизвестное, потом решаем. skidline Помощь студентам 1 14.06.2013 20:16
Вычислить количество недель сначало года Alexandr- Помощь студентам 0 02.04.2013 15:22