Multi row to a row sql - sql

I have a table as bellow:
I want query to print output as bellow:

Note: Please, do not downvote. I know the rules of posting answers, but for such of questions there's no chance to post short answer. I posted it only to provide help for those who want to find out how to achieve that, but does not expect ready-to-use solution.
I'd suggest to read these articles:
PIVOT on two or more fields in SQL Server
Pivoting on multiple columns - SQL Server
Pivot two or more columns in SQL Server 2005

At first UNPIVOT then PIVOT. If number of rows for each Pod_ID is not always equal 3 then you need to use dynamic SQL. The basic sample:
SELECT *
FROM (
SELECT Pod_ID,
Purs + CASE WHEN RN-1 = 0 THEN '' ELSE CAST(RN-1 as nvarchar(10)) END as Purs,
[Values]
FROM (
SELECT Pod_ID,
Pur_Qty, --All columns that will be UNPIVOTed must be same datatype
Pur_Price,
CAST(ETD_Date as int) ETD_Date, -- that is why I cast date to int
ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as RN
FROM YourTable
) as p1
UNPIVOT (
[Values] FOR [Purs] IN(Pur_Qty, Pur_Price, ETD_Date)
) as unpvt
) as p2
PIVOT (
MAX([Values]) FOR Purs IN (Pur_Qty,Pur_Price,ETD_Date,Pur_Qty1,Pur_Price1,ETD_Date1,Pur_Qty2,Pur_Price2,ETD_Date2)
) as pvt
Will bring you:
Pod_ID Pur_Qty Pur_Price ETD_Date Pur_Qty1 Pur_Price1 ETD_Date1 Pur_Qty2 Pur_Price2 ETD_Date2
F8E2F614-75BC-4E46-B7F8-18C7FC4E5397 24 22 20160820 400 33 20160905 50 44 20160830

Related

Convert SQL table from Long Data to Wide Data

I have an SQL table that contains survey data. Unfortunately, the survey questions are long data instead of wide data (I have a column that has all the question numbers and I need the question numbers to be their own columns).
I have:
question_id | question_format_id | response----- | format_type | question
---63-------|------8-------------|--synchronous--|--likert-----|How will you attend class
---64-------|------3-------------|--COVID concern|short answer-|Reason for selection
I want:
63 ----------------------| 64
8------------------------| 3
synchornous--------------| COVID concern
likert modality----------| short answer
How will you attend class| Reason for selection
Is that possible?
The reason is that I'm trying to do reporting on students that select a certain answer for question 63. However, as soon as I put a filter on the responses for the questions, I no longer see both questions.
Any suggestions would be appreciated.
Firstly the UNPIVOT clause , and then PIVOT clause might be applied such as
SELECT [1] AS col1, [2] AS col2
FROM
(
SELECT *
FROM ( SELECT CAST(question_id AS VARCHAR(MAX)) AS question_id,
CAST(question_format_id AS VARCHAR(MAX)) AS question_format_id,
response,format_type,question,
ROW_NUMBER() OVER (ORDER BY question_id) AS rn
FROM [tab] ) t
UNPIVOT
(val FOR col IN
(question_id,question_format_id,response,format_type,question)
) AS upt
) ut
PIVOT
(
MAX(val) FOR rn IN ([1],[2])
) AS pt
in order to transpose the values in a vertical manner.
Demo

SQL Server [PATSTAT] query | Multiple charindex values &

Hello Stack Overflow Community.
I am retrieving data with SQL from PATSTAT (patent data base from the European Patent Office). I have two issues (see below). For your info the PATSAT sql commands are quite limited.
I. Charindex with multiple values
I am looking for specific two specific patent groups ["Y02E" and "Y02C"] and want to retrieve data on these. I have found that using the charindex function works if I insert one group;
and charindex ('Y02E', cpc_class_symbol) > 0
But if I want to use another charindex function the query just times out;
and charindex ('Y02E', cpc_class_symbol) > 0 or charindex ('Y02C', cpc_class_symbol) >0
I am an absolute SQL rookie but would really appreciate your help!
II. List values from column in one cell with comma separation
Essentially I want to apply what I found as the "string_agg"-command, however, it does not work for this database. I have entries with a unique ID, which have multiple patent categories. For example:
appln_nr_epodoc | cpc_class_symbol
EP20110185794 | Y02E 10/125
EP20110185794 | Y02E 10/127
I would like to have it like this, however:
appln_nr_epodoc | cpc_class_symbol
EP20110185794 | Y02E 10/125, Y02E 10/127
Again, I am very new to sql, so any help is appreciated! Thank you!
I will also attach the full code here for transparency
SELECT a.appln_nr_epodoc, a.appln_nr_original, psn_name, person_ctry_code, person_name, person_address, appln_auth+appln_nr,
appln_filing_date, cpc_class_symbol
FROM
tls201_appln a
join tls207_pers_appln b on a.appln_id = b.appln_id
join tls206_person c on b.person_id = c.person_id
join tls801_country on c.person_ctry_code= tls801_country.ctry_code
join tls224_appln_cpc on a.appln_id = tls224_appln_cpc.appln_id
WHERE appln_auth = 'EP'
and appln_filing_year between 2005 and 2012
and eu_member = 'Y'
and granted = 'Y'
and psn_sector = 'company'
and charindex ('Y02E', cpc_class_symbol) > 0
For your part 2 here is a sample data i created
And here is the code. It gives me YOUR requested output.
create table #test_1 (
appln_nr_epodoc varchar(20) null
,cpc_class_symbol varchar(20) null
)
insert into #test_1 values
('EP20110185794','Y02E 10/125')
,('EP20110185794','Y02E 10/127')
,('EP20110185795','Y02E 10/130')
,('EP20110185796','Y02E 20/140')
,('EP20110185796','Y02E 21/142')
with CTE_1 as (select *
from (
select *
,R1_1 = Rank() over(partition by appln_nr_epodoc order by cpc_class_symbol )
from #test_1
) as a
where R1_1 = 1
)
,CTE_2 as (select *
from (
select *
,R1_1 = Rank() over(partition by appln_nr_epodoc order by cpc_class_symbol )
from #test_1
) as a
where R1_1 = 2 )
select a.appln_nr_epodoc
,a.cpc_class_symbol+','+c.cpc_class_symbol
from CTE_1 a
join CTE_2 c on c.appln_nr_epodoc = a.appln_nr_epodoc
Out put

SQL Server - If the field had been pivot, how to pivot again by another field? Is that the DB design correct?

I have a raw data like
Title Question Answer AnswerRemark
----------------------------------------
ACCCode1 Q1 Y NULL
ACCCode1 Q2 N 6
ACCCode1 Q3 Y Workout
As you can see the field "AnswerRemark" is free text for "Answer", some answer is not require remark.
I can simply pivot the question and answer like:
Title Q1 Q2 Q3
AccessCode1 Y N Y
My desired Result will be
Title Q1 R1 Q2 R2 Q3 R3
AccessCode1 Y NULL N 6 Y Workout
Is that possible? I can not figure it out how to achieve this, pivot the Answer is not good idea as it have many combinations.
Any suggestion?
Use Conditional Aggregation :
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
Using Pivot we get the result
;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
Using Dynamic Sql where the columns are not static
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,'+#CombineColumn+' From
(
SELECT Title,'+#MAxDyColumn1+','+#MAxDyColumn2+' FRom
(
SELECT * FROM #t
)AS SRC
PIVOT
(
MAX(Answer) FOR Question IN('+#DyColumn1+')
) AS Pvt1
PIVOT
(
MAX(AnswerRemark) FOR Question2 IN('+#DyColumn2+')
) AS Pvt2
GROUP BY Title
)dt
'
PRINT #Sql
EXEC(#Sql)
Result
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
I don't know how big your data is, or how many questions are possible. A more generic Q&A structure done at the presentation layer would be far better, but for your specific request a more correct design would be a 3NF table. This will allow you to create a primary key that is highly optimised and create a secondary index by question type id. All your keys are now IDs which are far faster to search and match than strings:
Account Codes
AccID - AccName - columns for other data related to accounts
Stores each account you have.
Questions
QuestionID - QuestionName
List of possible questions, one row for every question you have, Q1, Q2 etc. You could add question categories here to exploit any commonality you have, e.g. if you have different surveys with the same set of questions, you could put them in one category and easily then query the below.
Results
AccId, QuestionID, Result, Result Remark
Contains one row for every question asked.
Query for your result still uses pivot, but now you can select the list of columns to use from a variable or dynamic SQL syntax, which means you can control it somewhat better and hte query itself should be better.
With that said, if you have any knowledge about your data whatsoever you can use it to make a static query which can then be indexed. Examples are here of this query: SQL Server 2005 Pivot on Unknown Number of Columns. You can then set the column names if required using the AS syntax, which unfortunately would require dynamic sql again (Change column name while using PIVOT SQL Server 2008).
By the way, what you are trying to do is specifically dealing with denormalised data, which is what nosql is good for, SQL Server gives you great help but you have to have some structure to your data.
If you aren't working for survey monkey and dealing with millions of variations, I'd seriously look at whether you can just make a table specific to each round of questions you get, and then simply denormalise it and add an explicit columns for each question and then make your entire logic just a select * from surveyxyztable where accountid = abc.

pivoting result in SQL Server

I have the following SQL:
SELECT
PhaseId,
COUNT(JoinId)
FROM Joins
GROUP BY
PhaseId
OUTPUT:
1 143
2 65
3 86
I usually pivot the result by using the case technique for each column, but now I'm trying to use the PIVOT statement unsuccessfully. Can anyone point me in the right direction?
I feel like there are many examples out there, but PIVOT is hard to wrap your head around, so:
SELECT *
FROM
( SELECT PhaseId,JoinID
FROM YourTable
) AS T1
PIVOT (COUNT(JoinID) FOR PhaseId IN ([1],[2],[3])) AS T2

T-SQL Pivot/Unpivot(Transpose) Column Headers Needed as Data Rows

I'm working on a T-SQL issue where I needed to Transponse Rows into Columns and using UNPIVOT and PIVOT together per a post at Simple way to transpose columns and rows in Sql?
No problem. It does Exactly what I want with the row/column manipulation. However what I would REALLY like to do is to get the values used for the column headers to become yet another row in the results.
My abbreviated code is:
SELECT *
FROM (SELECT fiscalyear,
Sum(totalrecords) AS TotalRecords
FROM dbo.tbleirstatisticsoverviewsummary
WHERE fiscalquarter = 'ALL'
AND branchcode = 'ALL'
GROUP BY fiscalyear,
fiscalquarter,
branchcode) AS p
UNPIVOT (value
FOR colname IN ( totalrecords )) AS unpvt
PIVOT (Max(value) For FiscalYear IN ([2012],[2013],[ALL])) as p
What it renders is:
colname 2012 2013 ALL
TotalRecords 421 227 648
Where the first line is column headers.
Any thoughts on how I could get the column headers to be data rows?
Adding some sample Raw Data
fiscalyear TotalRecords
2012 421
2013 227
ALL 648
There are a few confusing things that you are doing.
First, typically you will unpivot multiple columns. Right now, you are are unpivoting one column and it seems like you are doing it just to rename the column?
Second, you are aggregating the data twice, the PIVOT should be able to handle the aggregation using SUM().
Third, it is not exactly clear on why you need the column headers as a row, what will you want the column headers to be called?
Based on your sample data you should be able to just apply the PIVOT function:
select 'TotalRecords' TotalRecords,
[2012],
[2013],
[All]
from tbleirstatisticsoverviewsummary
pivot
(
sum(totalrecords)
for FiscalYear IN ([2012],[2013],[ALL])
) p;
See SQL Fiddle with Demo. Then if you want a row with the columns headers, then you can use a UNION ALL:
select 'colname' col1,
2012 col2,
2013 col3,
'All' col4
union all
select 'TotalRecords' TotalRecords,
[2012],
[2013],
[All] = cast([all] as varchar(10))
from tbleirstatisticsoverviewsummary
pivot
(
sum(totalrecords)
for FiscalYear IN ([2012],[2013],[ALL])
) p;
See SQL Fiddle with Demo