У меня эти две таблицы:
TableA:
aid ! name
--- ! -----
1 ! Paper
2 ! Rock
3 ! Sciz
Table B (aid is TableA FKEY)
id ! aid ! area ! mode
-- ! --- ! ----- ! ----
1 ! 1 ! 200 ! 1
2 ! 1 ! 240 ! 2
3 ! 2 ! 300 ! 1
4 ! 2 ! 290 ! 2
5 ! 3 ! 100 ! 1
6 ! 3 ! 110 ! 2
Я хочу написать запрос, который вернет следующие результаты:
aid ! area(mode=1) ! area(mode=2)
--- ! ------------ ! ------------
1 ! 200 ! 240
2 ! 300 ! 290
3 ! 100 ! 110
Как это сделать в mySQL? Мне также необходимо исключить случаи, когда таблица В содержит только значение для режима 1, а не для режима2, и наоборот.
Благодарю.
Это процесс называется pivot.
И может быть сделано с использованием GROUP BY в сочетании с предложениями MAX(CASE END)
.
Предложение HAVING гарантирует, что у B.aid есть обе записи, содержащие 1 и 2 режима.
SELECT
B.aid
, MAX(CASE WHEN B.mode = 1 WHEN B.area ELSE 0 END) AS 'area(mode=1)'
, MAX(CASE WHEN B.mode = 2 WHEN B.area ELSE 0 END) AS 'area(mode=2)'
FROM
B
GROUP BY
B.aid
HAVING
SUM(B.mode = 1) = 1
AND
SUM(B.mode = 2) = 1
ORDER BY
B.aid ASC
http://sqlfiddle.com/#!9/2db6c5/1
Попробуй это;
SELECT b1 .aid, b1.area, b2.area
FROM tablea a1
LEFT JOIN tableb b1 ON a1.aid = b1 .aid
LEFT JOIN tableb b2 ON a1.aid = b2 .aid
where
b1.mode = 1
and b2.mode = 2
Если вам нужны оба режима, я бы предложил использовать inner join
:
SELECT a.aid, b1.area, b2.area
FROM tablea a1 JOIN
tableb b1
ON a1.aid = b1.aid AND b1.mode = 1 JOIN
tableb b2
ON a1.aid = b2.aid AND b2.mode = 2;
Внутреннее соединение гарантирует, что оба значения присутствуют в b
.
Поскольку оба режима должны присутствовать, вам фактически не нужна tablea
:
SELECT b1.aid, b1.area, b2.area
FROM tableb b1
ON a1.aid = b1.aid JOIN
tableb b2
ON a1.aid = b2.aid AND b1.mode = 1 AND b2.mode = 2;
На самом деле, если вам просто нужна aid
где оба присутствуют, вы также можете:
select b.aid, max(case when mode = 1 then area end) as area1,
max(case when mode = 2 then area end) as area2
from tableb b
group by b.aid
having area1 is not null and area2 is not null;
Это не требует объединения таблиц вообще.
Я не знаю, почему TableA является целью таблицы A. Но я думаю, что это будет начальная точка.
SELECT DISTINCT a.aid
,b1.area as area_mode1
,b2.area as area_mode2
FROM TableA a
JOIN TableB b1 ON (a.aid = b1.aid AND b1.mode = '1')
JOIN TableB b2 ON (a.aid = b2.aid AND b2.mode = '2')
;
Может быть, SUBSELECT тоже сделает трюк, но я думаю, что двойной JOIN таблицы B будет стоить меньше памяти для больших таблиц.
Подсказка: вам следует избегать имен полей, таких как "имя" и "режим". Это зарезервированные слова в SQL и могут привести к запутывающим результатам.
Это должно работать:
select * from(
select aid, max(case when mode = 1 then area end) as mode1,
max(case when mode = 2 then area end) as mode2
from tableB
group by aid order by aid
)where mode1 is not null and mode2 is not null
mode = 1
илиmode = 2
?