2013-11-25 8 views
-3

Пожалуйста, помогите мне в преобразовании строк в столбцы, а не их дублировании. Я искал и применял способы сделать это, но я не могу удовлетворить свои требования.SQL Строки в столбцы

create table PROGRAMMER 
(
PERSON varchar(15), 
LANGUAGE varchar(20), 
LEVELS varchar(15) 
); 

insert into PROGRAMMER (PERSON, LANGUAGE, LEVELS) values ('CARL', 'JAVA', 'SENIOR'); 
insert into PROGRAMMER (PERSON, LANGUAGE, LEVELS) values ('CARL', 'PHP', 'MID'); 
insert into PROGRAMMER (PERSON, LANGUAGE, LEVELS) values ('CARL', 'VB.NET', 'JUNIOR'); 
insert into PROGRAMMER (PERSON, LANGUAGE, LEVELS) values ('GARY', 'C#', 'MID'); 
insert into PROGRAMMER (PERSON, LANGUAGE, LEVELS) values ('GARY', 'VB.NET', 'MID'); 
insert into PROGRAMMER (PERSON, LANGUAGE, LEVELS) values ('RALPH', 'PHP', 'SENIOR'); 
insert into PROGRAMMER (PERSON, LANGUAGE, LEVELS) values ('RALPH', 'RUBY', 'JUNIOR'); 
insert into PROGRAMMER (PERSON, LANGUAGE, LEVELS) values ('RALPH', 'JAVASCRIPT', 'SENIOR'); 

Я хочу представить таблицу, как этого, используя «УРОВНЕЙ» в качестве столбца с несколько строк, имеющих тот же самый человек столько раз, сколько они имеют одинаковые уровни на разных языках. Остальные столбцы будут пустыми, если нет записи.

| PERSON | SENIOR | MID | JUNIOR | 
---------------------------------------------- 
| CARL | JAVA | PHP | VB.NET | 
| GARY |   | C#  |   | 
| GARY |   | VB.NET |   | 
| RALPH | PHP |   | RUBY | 
| RALPH |JAVASCRIPT|   |   | 

спасибо.

+1

Строки и столбцы не являются взаимозаменяемый в SQL. Вы можете упорядочить строки с помощью 'ORDER BY', и вы не знаете их счет заранее. Вы можете указывать только порядок столбцов при записи запроса, и их количество известно во время записи запроса. Вероятно, вы должны полностью переосмыслить свой дизайн. –

+0

Вы создаете столбец как платформу и вставляете как уровень? Оба ошибаются. У вас не может быть столбца с именем LEVEL. – SriniV

+0

от этого я угадываю его на _pivot_? –

ответ

3

Вы не можете достичь этого с транспонированной. а попробуйте использовать natural full outer join

WITH T 
    AS (SELECT 
      P.*, 
      ROW_NUMBER () 
       OVER (PARTITION BY PERSON, LEVELS ORDER BY LANGUAGE) 
       R 
     FROM 
      PROGRAMMER P) 
SELECT 
     PERSON, 
     SENIOR, 
     MID, 
     JUNIOR 
FROM 
     (SELECT 
      PERSON, 
      R, 
      LANGUAGE SENIOR 
     FROM 
      T 
     WHERE 
      LEVELS = 'SENIOR') 
     NATURAL FULL OUTER JOIN (SELECT 
           PERSON, 
           R, 
           LANGUAGE MID 
          FROM 
           T 
          WHERE 
           LEVELS = 'MID') 
     NATURAL FULL OUTER JOIN (SELECT 
           PERSON, 
           R, 
           LANGUAGE JUNIOR 
          FROM 
           T 
          WHERE 
           LEVELS = 'JUNIOR'); 

Вы

PERSON   SENIOR    MID     JUNIOR    
--------------- -------------------- -------------------- -------------------- 
CARL   JAVA     PHP     VB.NET    
GARY         C#          
GARY         VB.NET         
RALPH   JAVASCRIPT        RUBY     
RALPH   PHP               

5 rows selected. 
+0

Это здорово! Да, это именно то, чего я хотел достичь, я вообще не знал о Natural Joins, так как я только начал изучать SQL. Будет ли это работать и с SQL Server?Я просто попробую вместо этого. – law

+0

Там нет ничего особенного в 'NATURAL', это просто для элегантности. Для всех типов соединений, кроме FULL OUTER JOIN, я бы рекомендовал использовать 'A [INNER, LEFT OUTER, RIGHT OUTER] JOIN B ON (A.COL1 = B.COL1)', с последующей ссылкой на COL1, квалифицированный как A.COL1 для 'LEFT OUTER JOIN' или B.COL1 для' RIGHT OUTER JOIN'. NATURAL соответствует FULL OUTER JOIN, потому что без него вам придется ссылаться на объединение столбца COL1 как «COALESCE (A.COL1, B.COL1, C.COL1, ...) AS ACTUAL_COL1'. Я понятия не имею, поддерживает ли SQL Server FOJ - если нет, вам нужно будет выполнить (UNIX LEFT OUTER JOIN B) (B NOT IN A) ' – KevinKirkpatrick

+0

Также - если вы использовали Oracle, измените VARCHAR на VARCHAR2. Google может объяснить, почему :-) – KevinKirkpatrick

0
  1. Вы не можете создать столбец с названием «УРОВЕНЬ» в оракуле с его зарезервированным ключевым словом.
  2. Вы создаете утверждения в таблицах и вставках, противоречащих
  3. Каждый человек может быть связан с несколькими языками с одинаковым уровнем владения. Таким образом, невозможно транспонировать на основе уровней.
  4. Скорее вы можете попробовать транспонировать на основе языков.
  5. Если у вас есть окончательный список языков, вы можете использовать MAX и DECODE
  6. PIVOT нельзя использовать, так как ему нужна сводная функция на строке. !!
  7. Если вы не имеете окончательный список, то вы можете использовать Oracle подключения по

Попробуйте это, если у вас есть окончательный список языков

SELECT 
     X.PERSON, 
     MAX (DECODE (X.LANGUAGE, 'JAVA', X.LEVELS)) "JAVA", 
     MAX (DECODE (X.LANGUAGE, 'PHP', X.LEVELS)) "PHP", 
     MAX (DECODE (X.LANGUAGE, 'VB.NET', X.LEVELS)) "VB.NET", 
      MAX (DECODE (X.LANGUAGE, 'C#', X.LEVELS)) "C#", 
     MAX (DECODE (X.LANGUAGE, 'RUBY', X.LEVELS)) "RUBY", 
     MAX (DECODE (X.LANGUAGE, 'JAVASCRIPT', X.LEVELS)) "JAVASCRIPT" 
FROM 
     (SELECT 
      O.PERSON, 
      O.LEVELS, 
      O.LANGUAGE 
     FROM 
      PROGRAMMER O) X 
GROUP BY 
     X.PERSON; 


PERSON   JAVA   PHP    VB.NET   C#    RUBY   JAVASCRIPT  
--------------- --------------- --------------- --------------- -------------- --------------- --------------- 
CARL   SENIOR   MID    JUNIOR       
GARY           MID    MID    
RALPH       SENIOR           JUNIOR   SENIOR   

3 rows selected. 
+0

Я вижу, что в этой таблице это лучший способ представить запрос. Но для моего требования были те проблемы, с которыми меня попросили найти способ решить. Уровни являются определенными, чтобы быть этими тремя только «старшими», «средними», «младшими». Я думаю, что головоломка, которую я должен решить, - это то, как я могу представить это, где человек может быть в два ряда, в зависимости от того, имеет ли он 2 языка в одном и том же знании. – law

+0

Так что это не транспонирование. Кевин получил это правильно – SriniV

0

это хороший вызов в проектировании подзапросов, попробуйте этот запрос на вашем столе PROGRAMMER как вы сказали:

select t1.person,t1.language as SENIOR,t2.language as MID,t3.language as JUNIOR 
from 
(select person,language from PROGRAMMER where levels = 'SENIOR' union all 
select distinct person,null as language from PROGRAMMER where person not in(select distinct person from PROGRAMMER where levels = 'SENIOR'))t1, 
(select person,language from PROGRAMMER where levels = 'MID' union all 
select distinct person,null as language from PROGRAMMER where person not in(select distinct person from PROGRAMMER where levels = 'MID'))t2, 
(select person,language from PROGRAMMER where levels = 'JUNIOR' union all 
select distinct person,null as language from PROGRAMMER where person not in(select distinct person from PROGRAMMER where levels = 'JUNIOR'))t3 
where 
t1.person = t2.person and t1.person = t3.person; 
+0

Hamidreza, да, это был хороший, но сложный вызов для меня, ваш ответ в моей тестовой таблице дублирует «RUBY» для «RALPH», поэтому он не отвечал требованиям. Тем не менее, спасибо, возможно, есть способ изменить ваш запрос, который покажет этот результат. Мне нравится смотреть на разные способы чего-то добиться. – law

Смежные вопросы