SQL SELECT MAX работает не так, как предполагалось

#sql #select #group-by #max

Вопрос:

 SELECT hbgu.jid,
       hbgu.id AS id,
       hbgu.group_id,
       MAX (hbgu.parent_id) AS parent_id,
       hbgu.jid,
       d.name
FROM hms_bbr_group_user hbgu
LEFT JOIN hms_doctor d
    ON hbgu.jid = d.jid
WHERE hbgu.group_id = 113
GROUP BY hbgu.id, d.name
 

У меня есть SELECT приведенное выше утверждение, которое пытается выбрать только максимальное значение столбца parent_id . В моем случае я хочу только parent_id = 114 потому, что это высшая ценность. Моя проблема в том, что отображаются не самые высокие значения, в чем, по-видимому, проблема?

1

Обновить:

Создать таблицу:

 CREATE TABLE public.hms_bbr_group_user
(
    id integer NOT NULL,
    group_id integer,
    parent_id integer,
    jid character varying(100) COLLATE pg_catalog."default",
    CONSTRAINT hms_bbr_group_user_pkey PRIMARY KEY (id)
)

CREATE TABLE public.hms_doctor
(
    jid character varying(50) COLLATE pg_catalog."default" NOT NULL,
    name character varying(100) COLLATE pg_catalog."default" NOT NULL,
    mobile character varying(50) COLLATE pg_catalog."default",
    operatorid integer,
    designationid integer NOT NULL,
    departmentid integer NOT NULL,
    pager character varying(50) COLLATE pg_catalog."default",
    mcr character varying(50) COLLATE pg_catalog."default",
    created_by character varying(50) COLLATE pg_catalog."default",
    created_date timestamp without time zone,
    updated_by character varying(50) COLLATE pg_catalog."default",
    updated_date timestamp without time zone,
    escalation_status integer NOT NULL DEFAULT 1,
    transport_type integer NOT NULL DEFAULT 0,
    extension character varying(50) COLLATE pg_catalog."default",
    hospitalid integer NOT NULL,
    type character varying COLLATE pg_catalog."default" NOT NULL DEFAULT 'doctor'::character varying,
    title character varying(35) COLLATE pg_catalog."default",
    subdeptid integer,
    sectionid integer,
    groupid integer,
    location character varying COLLATE pg_catalog."default",
    privacy_status integer NOT NULL DEFAULT 0,
    remote_status integer NOT NULL DEFAULT 1,
    display_priority integer NOT NULL DEFAULT 1000,
    fax character varying(50) COLLATE pg_catalog."default",
    divisionid integer,
    subsectionid integer,
    unitid integer,
    physical_location_id integer,
    areas_of_interest text COLLATE pg_catalog."default",
    CONSTRAINT hms_doctor_pkey PRIMARY KEY (jid)
)
 

Комментарии:

1. Помните, что выражения списка выбора должны функционально зависеть от GROUP BY терминов, в противном случае SQL на самом деле недействителен, даже если ваша база данных позволяет это. Пожалуйста, добавьте (к вопросу) CREATE TABLE утверждения для каждой таблицы вместе со всеми связанными ограничениями. Не изображайте, пожалуйста. Опубликуйте текст этих заявлений.

2. Я пошел дальше и добавил и CREATE TABLE то, и другое, если это поможет в чем-нибудь. hms_doctor немного длинновато, но мне нужен только один столбец для левого соединения.

3. также добавлены ограничения

4. Спасибо. Теперь , когда мы видим, что id это primary key из hms_bbr_group_user , это означает, что в каждой группе из этой таблицы есть только одна строка. Каких значений в результате вы не ожидали? Каждая группа имеет ровно один parent_id , поэтому MAX(hbgu.parent_id) на самом деле ничего не делает. Добавьте COUNT(DISTINCT hbgu.parent_id) в список избранных, чтобы увидеть это.

5. Как только ответ будет понят, следующим шагом будет определение ваших реальных требований. Можете ли вы задать новый вопрос с основным требованием? Какова была ваша конечная цель?

Ответ №1:

Ответ на новое требование:

Рабочий тестовый случай / скрипка

 WITH grps AS (
       SELECT jid, MAX(parent_id) AS max_parent
         FROM hms_bbr_group_user
        GROUP BY jid
     )
SELECT hbgu.jid
     , hbgu.id
     , hbgu.group_id
     , hbgu.parent_id
  FROM hms_bbr_group_user AS hbgu
  JOIN grps
    ON grps.jid = hbgu.jid
   AND grps.max_parent = hbgu.parent_id
;
 

Результат:

введите описание изображения здесь

Если все вышесказанное верно, следующим шагом будет просто добавить a JOIN в doctor таблицу.

Обновлена игра с подробностями о докторе

Обновленная скрипка

Ответьте с подробностями доктора:

 WITH grps AS (
       SELECT jid, MAX(parent_id) AS max_parent
         FROM hms_bbr_group_user
        GROUP BY jid
     )
SELECT hbgu.jid
     , hbgu.id
     , hbgu.group_id
     , hbgu.parent_id
     , d.name
  FROM hms_bbr_group_user AS hbgu
  JOIN grps
    ON grps.jid = hbgu.jid
   AND grps.max_parent = hbgu.parent_id
  JOIN hms_doctor AS d
    ON d.jid = grps.jid
;
 

Результат с подробностями доктора:

введите описание изображения здесь

Первоначальный ответ, объясняющий исходный результат запроса операции:

Это простая проблема функциональной зависимости.

Поскольку id это primary key часть таблицы, когда мы GROUP BY указываем этот столбец, на группу (из этой таблицы) может быть только одна строка и только одна parent_id на группу.

Запрос:

 SELECT hbgu.jid
     , hbgu.id AS id
     , hbgu.group_id
     , MAX (hbgu.parent_id) AS parent_id
     , hbgu.jid
  FROM hms_bbr_group_user hbgu
 WHERE hbgu.group_id = 113
 GROUP BY hbgu.id
;
 

Примечание: MAX в этом не было необходимости, так как гарантируется, что в каждой группе будет только одно parent_id значение, основанное на содержании primary key в GROUP BY условиях.

 SELECT hbgu.jid
     , hbgu.id AS id
     , hbgu.group_id
     , hbgu.parent_id
     , hbgu.jid
  FROM hms_bbr_group_user hbgu
 WHERE hbgu.group_id = 113
 GROUP BY hbgu.id
;
 

Для обоих вышеперечисленных случаев результатом является:

введите описание изображения здесь

Настройка:

 CREATE TABLE public.hms_bbr_group_user
(
    id integer NOT NULL,
    group_id integer,
    parent_id integer,
    jid character varying(100) COLLATE pg_catalog."default",
    CONSTRAINT hms_bbr_group_user_pkey PRIMARY KEY (id)
);

INSERT INTO hms_bbr_group_user VALUES
   (1, 113, 113, 'jhadmin')
 , (2, 113, 114, 'jhadmin')
;

CREATE TABLE public.hms_doctor
(
    jid character varying(50) COLLATE pg_catalog."default" NOT NULL,
    name character varying(100) COLLATE pg_catalog."default" NOT NULL
);

INSERT INTO hms_doctor VALUES
    ('jhadmin', 'Doctor jhadmin')
;
 

Ответ №2:

Это не проблема, вы сделали группу, id и name ( GROUP BY hbgu.id, d.name ), поэтому мы можем видеть, что у вас 2 группы, первая-это когда id =1 и второй, когда id = 2 и под parent_id колонки есть максимальное значение parent_id в группе, id равна 1, а вторая id 2, Если вам будут удалены из группы по hbgu.id области вы получите одну строку и parent_id будет 114. Просто MAX (hbgu.parent_id) AS parent_id это не условие, это означает, что нужно выбрать максимальное значение, выбранное parent_id по условию, которое вы установили