#sql #postgresql #subquery #max #left-join
#sql #postgresql #вложенный запрос #макс #левое соединение
Вопрос:
извиняюсь за название вопроса, я не был уверен, как описать эту проблему :
возьмите следующий CTE
WITH cte_form_answers AS (
SELECT fa.id
, MAX(CASE WHEN fa.question = 'contact' THEN fa.answer END) AS ContactMethod
FROM formanswers fa
GROUP BY fa.id)
SELECT * FROM cte_form_answers
id | ContactMethod
0 | Mobile
1 | Landline
и следующая таблица
SELECT id, ContactMethod, Contact from contacts
id | ContactMethod | Contact
0 | Mobile | xxxx-xxx-xxx
0 | Email | xxx@email.com
1 | Landline | xxxx-xxxx-xxx
1 | Mobile | xxx-xxx-xxxx
Я пытаюсь присоединиться, используя contatMethod из моего в моем CTE в таблицу контактов
Моя собственная попытка была :
WITH cte_form_answers AS (SELECT fa.id
, MAX(CASE WHEN fa.question = 'contact' THEN fa.answer END) AS ContactMethod
FROM formanswers fa
LEFT JOIN contacts c
ON c.id = fa.id
AND c.ContactMethod = ( SELECT fa1.id, MAX(CASE WHEN fa1.question = 'contact' THEN fa1.answer END)
FROM formanswers fa1 GROUP BY fa1.ID
GROUP BY fa.id)
что приводит к ошибке SQL Error [42601]: ERROR: subquery must return only one column Position: 722
Может кто-нибудь подсказать мне, как правильно это выполнить?
просто чтобы отметить, что таблица контактов представляет собой медленно меняющееся измерение, поэтому в ней есть end_date
столбец, который я также фильтрую в соединении, но я чувствую, что это не имеет значения для этого вопроса.
Ответ №1:
Вам нужно присоединиться к другой области, в которой вы агрегируете. Например:
WITH cte_form_answers AS (
SELECT fa.id,
MAX(fa.answer) FILTER(WHERE fa.question = 'contact') AS ContactMethod
FROM formanswers fa
GROUP BY fa.id
)
SELECT *
FROM cte_form_answers a
LEFT JOIN contacts c ON c.id = fa.id AND c.ContactMethod = a.ContactMethod
Или использование другого CTE, если вы предпочитаете:
WITH
cte_form_answers AS (
SELECT fa.id,
MAX(fa.answer) FILTER(WHERE fa.question = 'contact') AS ContactMethod
FROM formanswers fa
GROUP BY fa.id
),
cte_form_contact AS (
SELECT *
FROM cte_form_answers a
LEFT JOIN contacts c ON c.id = fa.id AND c.ContactMethod = a.ContactMethod
)
SELECT * FROM cte_form_contact
Комментарии:
1. Спасибо, я неправильно думал, чтобы решить это в рамках одного CTE? также я заметил, что вы используете filter вместо my
CASE WHEN
, из-за предпочтений или есть прирост производительности?2. @Manaskin: вам нужна другая область — либо CTE, либо подзапрос. Я не знаю, есть ли преимущество в производительности при использовании этого
filter()
предложения. Мне это нравится, потому что это аккуратнее (и это стандартный SQL тоже).3. Спасибо, GMB, ценю это