SQL-запрос с двумя значениями из одной таблицы в условиях, заданных столбцом в одной таблице

0

У меня эти две таблицы:

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, и наоборот.

Благодарю.

Теги:
database

5 ответов

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
2

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
  • 0
    что если есть несколько строк, у которых mode = 1 или mode = 2 ?
  • 0
    Ты прав. У моего upvote для скрипки проверенный ответ. Ты турок?
Показать ещё 1 комментарий
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;

Это не требует объединения таблиц вообще.

1

Я не знаю, почему 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 и могут привести к запутывающим результатам.

1

Это должно работать:

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
  • 0
    Присоединение не обязательно ... все ожидаемые данные уже находятся в таблице B.
  • 0
    @RaymondNijland ты прав. Я удалил таблицу А из своего ответа.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню