Adding aliasing to field names in Pivot SQL query - sql

I have a query below, and need to have field [Cmp-Goal-RF-148] (which is pivoted to be a column) - I need the column title to be something besides [Cmp-Goal-RF-148], so I suppose I need to alias it. Doing this throws up an error: ([Cmp-Goal-RF-148] AS 'Ghost'). What am I missing?
select *
from
(
select EmpRvwPdDtl.Emp, EmpRvwPdDtl.Rvwr,
EmpRvwPdDtl.RvwItm,
CAST(EmpRvwPdDtl.RvwItmCom as VARCHAR(MAX)) as comment
from EmpRvwPdDtl
inner join EmpRvwPd
on (EmpRvwPd.Emp=EmpRvwPdDtl.Emp)
where EmpRvwPdDtl.RvwItmCom is not null
AND EmpRvwPd.Sup='RM04'
) as s
PIVOT
(
MAX(comment) for RvwItm in ([Cmp-Goal-RF-148])
) as pvit

You will add the alias in the final SELECT list:
select Emp, Rvwr,
[Cmp-Goal-RF-148] as Ghost -- alias goes here
from
(
select EmpRvwPdDtl.Emp, EmpRvwPdDtl.Rvwr,
EmpRvwPdDtl.RvwItm,
CAST(EmpRvwPdDtl.RvwItmCom as VARCHAR(MAX)) as comment
from EmpRvwPdDtl
inner join EmpRvwPd
on (EmpRvwPd.Emp=EmpRvwPdDtl.Emp)
where EmpRvwPdDtl.RvwItmCom is not null
AND EmpRvwPd.Sup='RM04'
) as s
PIVOT
(
MAX(comment) for RvwItm in ([Cmp-Goal-RF-148])
) as pvit

Related

About SQL pivot query

This is static pivot query:
SELECT
*
FROM
(SELECT
PI.PRODID||' '||' ('||PI.PRODNAME||' - '||PI.PACKSIZE||')' PNAME,I.SIA_ID, IP.SALES_QTY
FROM
DIS_INVOICE_INFO I, DIS_INVOICE_PRODUCT IP, MKT_PROD_INFO PI
WHERE
I.SLNO = IP.SLNO
AND PI.PRODID = IP.PRODID) s
PIVOT
(SUM(SALES_QTY)
FOR SIA_ID IN (10080, 10084, 10082)
) pvt
But I want a dynamic query.
Like:
......
PIVOT
(SUM(SALES_QTY)
FOR SIA_ID IN (SELECT DISTINCT SIA_ID FROM DIS_INVOICE_INFO)
) pvt
You didn't mention about your DBMS, I don't know for the other DBMS systems but for Oracle you may make it dynamic provided you're producing XML results as in the following case :
SELECT
*
FROM
(SELECT PI.PRODID||' '||' ('||PI.PRODNAME||' - '||PI.PACKSIZE||')' PNAME,
I.SIA_ID, IP.SALES_QTY
FROM DIS_INVOICE_INFO I
INNER JOIN DIS_INVOICE_PRODUCT IP
ON (I.SLNO = IP.SLNO)
INNER JOIN MKT_PROD_INFO PI
ON (PI.PRODID = IP.PRODID)) s
PIVOT XML
(SUM(SALES_QTY)
FOR SIA_ID IN (SELECT DISTINCT SIA_ID FROM DIS_INVOICE_INFO)
) pvt;
By using the following DDL statements ;
create table DIS_INVOICE_INFO(SIA_ID int, SLNO int);
create table DIS_INVOICE_PRODUCT(PRODID int, SALES_QTY int, SLNO int);
create table MKT_PROD_INFO(PRODID int,PRODNAME varchar(90),PACKSIZE int);
insert all
into DIS_INVOICE_INFO values(10080,1);
into DIS_INVOICE_PRODUCT values(1,100,1);
into MKT_PROD_INFO values(1,'Milk',200);
select * from dual;
You get the following results for the above SQL-Select statement :
PNAME SIA_ID_XML
------------ ----------
(Milk - 200) <CLOB>
where <CLOB> is
<PivotSet><item><column name = "SIA_ID">10080</column>
<column name = "SUM(SALES_QTY)">100</column></item></PivotSet>
P.s. You cannot use PIVOT dynamically without XML option, I mean need to list all arguments explicitly within IN clause as in your case.

SQL merging rows with dynamic column headings

I am trying to populate a Gridview to have checkboxes enabled per student, but depending to certain values from this query:
#SelectedDate is provided via a TextBox as a date only
SELECT v1.StudentID,
v1.StudentPreferredName + ' ' + v1.StudentFamilyName AS StudentName,
bcs.CheckStatusName,
rce.DateSubmitted,
rcp.RollCallPeriod
FROM tblBoardingRollCallEntries AS rce
INNER JOIN vwBoardingTenants AS v1
ON v1.StudentID = rce.StudentID
AND v1.[Year] = YEAR(#SelectedDate)
INNER JOIN tblBoardingCheckStatus AS bcs
ON bcs.CheckStatusID = rce.CheckStatusID
AND bcs.StatusActive = 1
INNER JOIN tblBoardingRollCallPeriods AS rcp
ON rcp.RollCallPeriodID = rce.RollCallPeriodID
AND rcp.PeriodYear = YEAR(#SelectedDate)
AND #SelectedDate BETWEEN rcp.PeriodStart AND rcp.PeriodEnd
AND rcp.RowStatus = 1
WHERE dbo.fnDateOnly(rce.DateSubmitted) = dbo.fnDateOnly(#SelectedDate)
My gridview:
Shows the following:
The data:
I want to be able to basically condense the rows in the GridView to be one student per row and the checkboxes ticked according to RollCallPeriod text.
I am playing with SQL pivots, to get the data to be as close as possible to what I am after so as to avoid code-behind, etc. However, I cannot get this to work.
select StudentID, [1],[10],[2],[3],[4],[5],[6],[7],[8],[9]
from
(
select StudentID, RollCallID, CheckStatusID
from tblBoardingRollCallEntries
unpivot
(
value for name in ([RollCallID],[StudentID],[CheckStatusID],[DateSubmitted],[StaffID])
) unpiv
) src
pivot
(
sum(RollCallPeriodID)
for RollCallPeriodID in ([1],[10],[2],[3],[4],[5],[6],[7],[8],[9])
) piv
I receive the following error:
Lookup Error - SQL Server Database Error: The type of column
"StudentID" conflicts with the type of other columns specified in the
UNPIVOT list.
Any other ideas?
Thanks
A couple of ways you can do this depending on your actual data.
This will give you the CheckStatusName as the value for the RollCallPeriod
SELECT *
FROM (
SELECT StudentName,
CheckStatusName,
RollCallPeriod
FROM [YourQueryGoesHere]
) t
PIVOT (
MAX(CheckStatusName)
FOR RollCallPeriod IN ([6:15 AM],[8:00 AM],[3:00 PM],[6:00 PM],[9:00 PM])
) p
Or you get the status and a COUNT() to show if that Student has a value for that CheckStatusName, RollCallPeriod
SELECT *
FROM (
SELECT StudentName,
CheckStatusName,
RollCallPeriod
FROM [YourQueryGoesHere]
) t
PIVOT (
COUNT(RollCallPeriod)
FOR RollCallPeriod IN ([6:15 AM],[8:00 AM],[3:00 PM],[6:00 PM],[9:00 PM])
) p
Two options:
Instead of unpivotting directly on tblBoardingRollCallEntries: first select columns cast to a VARCHAR(...) type in a derived table, then UNPIVOT the derived table. Shortened example:
select StudentID, RollCallID, CheckStatusID
from
(
SELECT ..., CAST(StudentId AS VARCHAR(128)) AS StudentId, ... FROM tblBoardingRollCallEntries)
) AS ups
unpivot
(
value for name in ([RollCallID],[StudentID],[CheckStatusID],[DateSubmitted],[StaffID])
) unpiv
Use CROSS APPLY (SELECT CAST(StudentId AS VARCHAR(128)) UNION ALL ... ) to unpivot, that way you can UNPIVOT casting the column directly to the appropriate type.

Insert Into using a WITH clause (CTE) causes a ORA-00928

I'm attempting to do an essentially very simple task, which is resulting in:
ORA-00928: missing SELECT keyword
All I'm trying to do is persist the results from periods into table globalTable. Selecting works fine (I'm returned rows) however as soon as I replace it with the Insert I get the above error.
create global temporary table globalTable
(
ids number(11)
);
with periods as
(
select cl.id uniqueId
from inv_mpan_hh_con_lines cl
left join invoice_vat_lines vl on
cl.invoice_id = VL.INVOICE_ID
where rownum < 4
)
--//Issue occurs at insert keyword. If I comment it and uncomment select it works as expected//--
--select uniqueId
insert into globalTable
from periods;
Any pointers are much appreciated.
Try this:
insert into globalTable
with periods as
(
select cl.id uniqueId
from inv_mpan_hh_con_lines cl
left join invoice_vat_lines vl
on cl.invoice_id = VL.INVOICE_ID
where rownum < 4
)
select uniqueId
from periods;
CTE (WITH-clause) is a part of SELECT statement, according to the INSERT syntax you can either specify values or SELECT statement

Unpivoting multiple columns

I have a table in SQL Server 2014 called anotes with the following data
and I want to add this data into another table named final as
ID Notes NoteDate
With text1, text2, text3, text4 going into the Notes column in the final table and Notedate1,notedate2,notedate3,notedate4 going into Notedate column.
I tried unpivoting the data with notes first as:
select createdid, temp
from (select createdid,text1,text2,text3,text4 from anotes) p
unpivot
(temp for note in(text1,text2,text3,text4)) as unpvt
order by createdid
Which gave me proper results:
and then for the dates part I used another unpivot query:
select createdid,temp2
from (select createdid,notedate1,notedate2,notedate3,notedate4 from anotes) p
unpivot (temp2 for notedate in(notedate1,notedate2,notedate3,notedate4)) as unpvt2
which also gives me proper results:
Now I want to add this data into my final table.
and I tried the following query and it results into a cross join :(
select a.createdid, a.temp, b.temp2
from (select createdid, temp
from (select createdid,text1,text2,text3,text4 from anotes) p
unpivot
(temp for note in(text1,text2,text3,text4)) as unpvt) a inner join (select createdid,temp2
from (select createdid,notedate1,notedate2,notedate3,notedate4 from anotes) p
unpivot (temp2 for notedate in(notedate1,notedate2,notedate3,notedate4)) as unpvt) b on a.createdid=b.createdid
The output is as follows:
Is there any way where I can unpivot both the columns at the same time?
Or use two select queries to add that data into my final table?
Thanks in advance!
I would say the most concise, and probably most efficient way to unpivot multiple columns is to use CROSS APPLY along with a table valued constructor:
SELECT t.CreatedID, upvt.Text, upvt.NoteDate
FROM anotes t
CROSS APPLY
(VALUES
(Text1, NoteDate1),
(Text2, NoteDate2),
(Text3, NoteDate3),
(Text4, NoteDate4),
(Text5, NoteDate5),
(Text6, NoteDate6),
(Text7, NoteDate7)
) upvt (Text, NoteDate);
Simplified Example on SQL Fiddle
ADDENDUM
I find the concept quite a hard one to explain, but I'll try. A table valued constuctor is simply a way of defining a table on the fly, so
SELECT *
FROM (VALUES (1, 1), (2, 2)) t (a, b);
Will Create a table with Alias t with data:
a b
------
1 1
2 2
So when you use it inside the APPLY you have access to all the outer columns, so it is just a matter of defining your constructed tables with the correct pairs of values (i.e. text1 with date1).
Used the link above mentioned by #AHiggins
Following is my final query!
select createdid,temp,temp2
from (select createdid,text1,text2,text3,text4,text5,text6,text7,notedate1,notedate2,notedate3,notedate4,notedate5,notedate6,notedate7 from anotes) main
unpivot
(temp for notes in(text1,text2,text3,text4,text5,text6,text7)) notes
unpivot (temp2 for notedate in(notedate1,notedate2,notedate3,notedate4,notedate5,notedate6,notedate7)) Dates
where RIGHT(notes,1)=RIGHT(notedate,1)
Treat each query as a table and join them together based on the createdid and the fieldid (the numeric part of the field name).
select x.createdid, x.textValue, y.dateValue
from
(
select createdid, substring(note, 5, len(note)) fieldId, textValue
from (select createdid,text1,text2,text3,text4 from anotes) p
unpivot
(textValue for note in(text1,text2,text3,text4)) as unpvt
)x
join
(
select createdid, substring(notedate, 9, len(notedate)) fieldId, dateValue
from (select createdid,notedate1,notedate2,notedate3,notedate4 from anotes) p
unpivot (dateValue for notedate in(notedate1,notedate2,notedate3,notedate4)) as unpvt2
) y on x.fieldId = y.fieldId and x.createdid = y.createdid
order by x.createdid, x.fieldId
The other answer given won't work if you have too many columns and the rightmost number of the field name is duplicated (e.g. text1 and text11).

Converting a pivot table to a flat table in SQL

I would like to transform a pivot table into a flat table, but in the following fashion: consider the simple example of this table:
As you can see, for each item - Address or Income -, we have a column for old values, and a column for new (updated values). I would like to convert the table to a "flat" table, looking like:
Is there an easy way of doing that?
Thank you for your help!
In order to get the result, you will need to UNPIVOT the data. When you unpivot you convert the multiple columns into multiple rows, in doing so the datatypes of the data must be the same.
I would use CROSS APPLY to unpivot the columns in pairs:
select t.employee_id,
t.employee_name,
c.data,
c.old,
c.new
from yourtable t
cross apply
(
values
('Address', Address_Old, Address_new),
('Income', cast(income_old as varchar(15)), cast(income_new as varchar(15)))
) c (data, old, new);
See SQL Fiddle with demo. As you can see this uses a cast on the income columns because I am guessing it is a different datatype from the address. Since the final result will have these values in the same column the data must be of the same type.
This can also be written using CROSS APPLY with UNION ALL:
select t.employee_id,
t.employee_name,
c.data,
c.old,
c.new
from yourtable t
cross apply
(
select 'Address', Address_Old, Address_new union all
select 'Income', cast(income_old as varchar(15)), cast(income_new as varchar(15))
) c (data, old, new)
See Demo
select employee_id,employee_name,data,old,new
from (
select employee_id,employee_name,adress_old as old,adress_new as new,'ADRESS' as data
from employe
union
select employee_id,employee_name,income_old,income_new,'INCOME'
from employe
) data
order by employee_id,data
see this fiddle demo : http://sqlfiddle.com/#!2/64344/7/0