2017-12-29 1 views
0

내가 어떤 대답은 말을 필요로하지 않는,SQL Server - 필드가 피벗 인 경우 다른 필드로 다시 피벗 (pivoting)하는 방법? DB 디자인이 맞습니까? 당신은 필드 "AnswerRemark"가 "대답"에 대한 무료 문자입니다 볼 수 있듯이

 

Title Question Answer AnswerRemark 
---------------------------------------- 
ACCCode1 Q1  Y  NULL 
ACCCode1 Q2  N  6 
ACCCode1 Q3  Y  Workout 

같은 원시 데이터를 가지고있다.

단순히 질문을 돌리와 같은 답변을 할 수 있습니다 그게 가능

 
Title   Q1 R1 Q2 R2 Q3 R3 
AccessCode1 Y NULL N 6  Y Workout 

될 것

 
Title   Q1 Q2 Q3 
AccessCode1 Y N Y 

내 원하는 결과? 나는 이것을 달성하는 방법을 이해할 수 없다. 많은 조합이 있기 때문에 대답은 좋지 않다.

의견이 있으십니까?

+0

많은 질문이있을 수 있습니까? 겨우 3? – Larnu

+0

답장을 보내 주셔서 감사합니다. 아니요, 많은 질문입니다. 사용자 요청에 따라 달라집니다. –

+0

무제한의 질문 및 답변을 받으실 수 있다면, 빨리 못 생길 것입니다. 이를 위해 동적 SQL을 사용해야 할 것입니다. 나중에이 작업을 수행 할 수있는 기회가 있는지 알 수 있지만 대부분의 솔루션이 성능이 좋지 않을 수 있습니다. 이러한 상황은 일반적으로 프레젠테이션 레이어에서 더 잘 수행됩니다. – Larnu

답변

0

피벗을 사용하여 우리는 결과를 얻을 열 정적없는 동적 SQL을 사용하여

;With cte(Title, Question,Answer,AnswerRemark) 
AS 
(
SELECT 'ACCCode1','Q1','Y',NULL  UNION ALL 
SELECT 'ACCCode1','Q2','N','6'  UNION ALL 
SELECT 'ACCCode1','Q3','Y','Workout' UNION ALL 
SELECT 'ACCCode1','Q2','N','7'  UNION ALL 
SELECT 'ACCCode1','Q1','Y',NULL  UNION ALL 
SELECT 'ACCCode1','Q3','N','9'  UNION ALL 
SELECT 'ACCCode1','Q1','N','4'  UNION ALL 
SELECT 'ACCCode1','Q2','N','Workout' UNION ALL 
SELECT 'ACCCode1','Q4','N','2'  UNION ALL 
SELECT 'ACCCode1','Q3','Y','Workout' UNION ALL 
SELECT 'ACCCode1','Q1','N','1'  UNION ALL 
SELECT 'ACCCode1','Q4','Y',NULL 
) 

SELECT *,'Remark'+CAST(ROW_NUMBER()OVER(ORDER BY (SELECT 1))AS varchar(10)) AS Question2 
, ROW_NUMBER()OVER(PArtition by Question Order by Question) AS Seq 
INTO #t FROM cte 

DECLARE @DyColumn1 Nvarchar(max), 
     @DyColumn2 Nvarchar(max), 
     @Sql Nvarchar(max), 
     @MAxDyColumn1 Nvarchar(max), 
     @MAxDyColumn2 Nvarchar(max), 
     @CombineColumn Nvarchar(max) 


SELECT @DyColumn1=STUFF((SELECT DISTINCT ', '+QUOTENAME(Question) FROM #t FOR XML PATH ('')),1,1,'') 
SELECT @DyColumn2=STUFF((SELECT ', '+QUOTENAME(Question2) FROM #t FOR XML PATH ('')),1,1,'') 

SELECT @MAxDyColumn1=STUFF((SELECT DISTINCT ', '+'MAX('+QUOTENAME(Question)+') AS '+QUOTENAME(Question) FROM #t FOR XML PATH ('')),1,1,'') 
SELECT @MAxDyColumn2=STUFF((SELECT ', '+'MAX('+QUOTENAME(Question2)+') AS '+QUOTENAME(Question2) FROM #t FOR XML PATH ('')),1,1,'') 

SELECT @CombineColumn=STUFF((SELECT DISTINCT ', '+QUOTENAME(Question)+','+QUOTENAME(Question2) FROM #t FOR XML PATH ('')),1,1,'') 



SET @Sql='SELECT Title,'[email protected]+' From 
(
SELECT Title,'[email protected]+','[email protected]+' FRom 
(
SELECT * FROM #t 
)AS SRC 
    PIVOT 
    (
    MAX(Answer) FOR Question IN('[email protected]+') 
    ) AS Pvt1 

    PIVOT 
    (
    MAX(AnswerRemark) FOR Question2 IN('[email protected]+') 
    ) AS Pvt2 
    GROUP BY Title 
    )dt 
' 
PRINT @Sql 
EXEC(@Sql) 

결과

Title Q1 Remark1 Q1 Remark2 Q1 Remark3 Q1 Remark4 Q2 Remark5 Q2 Remark6 Q2 Remark7 Q3 Remark8 Q3 Remark9 Q3 Remark10 Q4 Remark11 Q4 Remark12 
ACCCode1 Y NULL Y 1 Y 4 Y NULL N 6 N Workout N 7 Y Workout Y Workout Y 9 Y NULL Y 2 
+0

고마워요 Sreenu131. 다음 주에 당신의 대답을 시도해 보겠습니다. 실제로 나는 당신과 비슷한 샘플을 보았지만 시뮬레이트에 실패했습니다. 아마도 로직을 이해하지 못했을 것입니다. 다시 한번 감사드립니다. 윌 당신이 알려 드리겠습니다. –

+0

동적 인 SQL을 사용하여 정적 코드를 피할 수 있습니다. 동적으로 열을 생성합니다. – Sreenu131

+0

Sreenu131에 감사드립니다. 그냥 작은 수정 날 위해 작동합니다 : 동적 SQL은 테이블 선언을 결합해야하고 "SELECT * INTO #t FROM cte"를 "SELECT *"로 변경했습니다. 참고 + 'CAST (ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS varchar (10)) "질문 2"열로 작업해야하기 때문에 질문 2에서 #t FROM cte "로. 다시 한 번 감사드립니다! –

2

사용 조건 집계 :

SELECT Title, 
    MAX(CASE WHEN Question='Q1' THEN Answer END) as Q1 , 
    MAX(CASE WHEN Question='Q1' THEN AnswerRemark END) as R1 , 
    MAX(CASE WHEN Question='Q2' THEN Answer END) as Q2 , 
    MAX(CASE WHEN Question='Q2' THEN AnswerRemark END) as R2 , 
    MAX(CASE WHEN Question='Q3' THEN Answer END) as Q3 , 
    MAX(CASE WHEN Question='Q3' THEN AnswerRemark END) as R3 
FROM [tablename] 
GROUP BY Title 
+0

이것은 결정할 수있는 양의 질문과 답변으로 올바른 생각입니다. 그러나 OP는 이것이 사실이 아니라고 권고했다. – Larnu

0

데이터의 크기 또는 가능한 질문의 개수를 알 수 없습니다. 좀 더 일반적인 Q & 프리젠 테이션 계층에서 수행 된 구조는 훨씬 좋지만 특정 요청에 대해보다 정확한 디자인은 3NF 테이블이됩니다. 이렇게하면 매우 최적화 된 기본 키를 만들고 질문 유형 ID별로 보조 색인을 만들 수 있습니다. 이제 모든 키가 문자열보다 검색하고 일치하는 ID가 훨씬 더 빨라졌습니다.

Account Codes 
AccID - AccName - columns for other data related to accounts 

보유하고있는 각 계정을 저장합니다. 가능한 질문의

Questions 
QuestionID - QuestionName 

목록, 당신이 가진 모든 질문에, Q1, Q2 등 당신이 가지고있는 공통점, 예를 악용 여기에 질문 카테고리를 추가 할 수 있습니다 하나의 행 동일한 질문 세트를 사용하는 설문 조사가 서로 다른 경우 한 가지 범주에 넣을 수 있으며 아래에서 쉽게 쿼리 할 수 ​​있습니다.

Results 
AccId, QuestionID, Result, Result Remark 

모든 질문에 대해 하나의 행이 들어 있습니다.

결과에 대한 쿼리는 여전히 피벗을 사용하지만 변수 나 동적 SQL 구문에서 사용할 열의 목록을 선택할 수 있습니다. 즉, 더 나은 제어가 가능하고 hte 쿼리 자체가 개선되어야합니다.

그렇다면 데이터에 대한 지식이있는 경우이를 사용하여 인덱싱 할 수있는 정적 쿼리를 만들 수 있습니다. 이 쿼리에 대한 예제는 SQL Server 2005 Pivot on Unknown Number of Columns입니다. 그런 다음 필요에 따라 AS 구문을 사용하여 열 이름을 설정할 수 있습니다. 아쉽게도 동적 SQL이 다시 필요합니다 (Change column name while using PIVOT SQL Server 2008).

그런데 nosql이 유용한 비정규 화 된 데이터를 다루는 것이 SQL Server의 큰 도움이되지만 데이터 구조가 있어야합니다.

설문 조사 원숭이를 위해 일하지 않고 수백만 개의 변형을 다루는 경우, 나는 질문의 각 라운드마다 특정 테이블을 만들 수 있는지 여부를 심각하게 살펴본 다음이를 간단히 비정규 화하고 각 질문에 대한 명시 적 열을 선택하고 전체 논리를 단지 select * from surveyxyztable where accountid = abc으로 만듭니다.

+0

고마워요. 저의 테이블 구조는 당신의 말과 같습니다, 어쩌면 나는 추측 할 수 있습니다. 설문 조사표, 질문 표, 선택 표 및 선택 보충 표가 있습니다. 1 개의 설문은 많은 질문을 포함하고, 1 개의 질문은 많은 선택을 포함하고, 1 개의 선택은 보완 입력을 갖거나 보충 입력을 보류 할 수 있습니다. 나는 당신의 말처럼 그 테이블에 가입 할 수 있으며, 내가 대답 한 것과 같은 방법으로 피벗 할 수 있습니다. 그것은 나를 위해 99 %를 완료하고 이제는 문제를 정렬합니다. 프로젝트는 크지 않지만 수정할 필요가있을 때마다 dB 변경이 필요하고 프로젝트를 다시 빌드 할 때마다 한 테이블을 한 설문에 지정하고 싶지 않습니다. –