Как суммировать результаты двух разных запросов по разным столбцам?

Вот моя customers таблица:

идентификатор имя 1 абв 2 двоично-цифровой код 3 договориться 4 защита

и таблица shifts:

идентификатор идентификатор1 идентификатор2 1 1 2 2 1 3 1 3

мой ожидаемый результат:

имя число абв 3 двоично-цифровой код 1 договориться 1 защита 0

Поэтому я просто хочу посчитать, сколько раз customers.id находится в таблице shifts, неважно, в id1 или id2. И то, и другое может быть null.

Я могу показать таблицу для одного столбца, например:

SELECT t1.name, COUNT(t2.id1) AS num
FROM customers t1
INNER JOIN shifts t2
ON t2.id1=t1.id
WHERE t2.id1=t1.id
GROUP BY t2.id1

и, конечно, я могу сделать то же самое для id2. Но как я могу суммировать оба результата?

Я знаю, что могу использовать оператор +, например:

COUNT(t2.id1)+COUNT(t2.id2)

но фактический расчет совершенно другой, поскольку он также должен изменить положения JOIN и GROUP.

Поэтому я попытался суммировать результаты всех запросов, как предложено здесь:

SELECT q1.name, q1.num+q2.num
FROM 
    (SELECT t1.name, COUNT(t2.id1) AS num
    FROM customers t1
    INNER JOIN shifts t2
    ON t2.id1=t1.id
    WHERE t2.id1=t1.id
    GROUP BY t2.id1) AS q1,

    (SELECT t1.name, COUNT(t2.id2) AS num
    FROM customers t1
    INNER JOIN shifts t2
    ON t2.id2=t1.id
    WHERE t2.id2=t1.id
    GROUP BY t2.id2) AS q2
WHERE q1.name=q2.name

но он ничего не возвращает, поскольку предложение WHERE требует, чтобы оба запроса имели один и тот же name, а это невозможно. Если я удалю предложение WHERE, результаты будут неверными, поскольку я отбрасываю name второго запроса.

Как суммировать результаты двух разных запросов по разным столбцам?

для этого вам нужен полный внешний joij, которого нет в MySQL, но посмотрите дублирующую ссылку

nbk 19.08.2024 19:06

@nbk FULL OUTER JOIN не нужен, см. мой ответ.

Barmar 19.08.2024 19:08

Может ли один и тот же идентификатор быть в id1 и id2? Их нужно считать отдельно?

Barmar 19.08.2024 19:10

если у двух клиентов одинаковые имена, вы хотите, чтобы в результате были получены две строки или только одна?

ysth 19.08.2024 19:15

Почему отрицательный голос? Я показал примеры данных, ожидаемый результат, поиск, который я сделал, и мои попытки.

Mark 19.08.2024 19:23

@ysth Было бы довольно странно объединять результаты для двух разных клиентов только потому, что у них по совпадению одно и то же имя. Хотя было бы неплохо включить в результат идентификатор, чтобы различать их.

Barmar 19.08.2024 19:35

Любопытно, что мой вопрос и оба хороших ответа были отклонены.

Mark 19.08.2024 19:53
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
7
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Используйте оба id1 и id2 в своем ON состоянии.

SELECT t1.name, COUNT(t2.id) AS num
FROM customers t1
LEFT JOIN shifts t2
ON t1.id IN (t2.id1, t2.id2)
GROUP BY t1.name

Используйте LEFT JOIN и COUNT(t2.shift), чтобы получить нулевое количество клиентов, которые не работают ни в одной смене.

Это решение предполагает, что у вас нет id1 = id2, а если есть, каждый из них не должен участвовать в подсчете.

Вам также следует рассмотреть возможность нормализации таблицы shifts примерно так:

  • идентификатор
  • номер_шифта
  • идентификатор_клиента

Есть какие-нибудь комментарии о том, почему этот ответ был отклонен? Если не считать мелких опечаток в коде, похоже, все работает.

Kliment Merzlyakov 19.08.2024 19:31
Ответ принят как подходящий

Если shifts.id уникален, вы можете выполнить два левых соединения и использовать счетчик различных, как предлагает @ysth.

SELECT
  t1.name,
  COUNT(DISTINCT t2.id) + COUNT(DISTINCT t3.id) AS num
FROM customers t1
LEFT JOIN shifts t2 ON t2.id1 = t1.id
LEFT JOIN shifts t3 ON t3.id2 = t1.id
GROUP BY t1.name

Альтернативно вы можете использовать два подзапроса:

WITH shift1 AS (
  SELECT
    t1.name,
    COUNT(t2.id1) AS num
  FROM customers t1
  LEFT JOIN shifts t2 ON t2.id1 = t1.id
  GROUP BY t1.name
),

shift2 AS (
  SELECT
    t1.name,
    COUNT(t3.id1) AS num
  FROM customers t1
  LEFT JOIN shifts t3 ON t3.id2 = t1.id
  GROUP BY t1.name
),

shift_both AS (
  SELECT
    name,
    num
  FROM shift1

  UNION ALL

  SELECT
    name,
    num
  FROM shift2
)

SELECT
  name,
  SUM(num) AS num
FROM shift_both
GROUP BY name

вам нужно будет сделать count(distinct t2.id) + count(distinct t3.id), чтобы избежать умножения результатов

ysth 19.08.2024 19:17

Да, вы совершенно правы. Я отредактировал ответ.

Kliment Merzlyakov 19.08.2024 19:20

Мне ваши два левых соединения понравились гораздо больше :)

ysth 19.08.2024 19:22

Да, я тоже :) Сначала я не заметил, что shifts.id, скорее всего, должен быть уникальным. Я сохранил два левых соединения в ответе с вашим обновлением. Спасибо!

Kliment Merzlyakov 19.08.2024 19:26

Да, shifts.id уникален. Решение LEFT JOIN работает отлично и очень элегантно.

Mark 19.08.2024 19:26

Да, я имел в виду t2.id и t3.id... отличный улов!

Kliment Merzlyakov 19.08.2024 19:32

@Марк, это была опечатка с моей стороны. Вы использовали последнюю версию с COUNT(DISTINCT t2.id)? Изначально я написал COUNT(DISTINCT t2.id1), что неверно.

Kliment Merzlyakov 19.08.2024 19:50

Да, моя вина. Я не видел обновления. Я удалил комментарий, потому что в конце концов увидел его и снова протестировал. Все работает нормально, не беспокойтесь!

Mark 19.08.2024 19:51

Другие вопросы по теме