Using the following example data:
INVNUM ORDNUM SHIPNUM INVLINE CHGCODE TAXBODY TAXRATE
I1 O1 0 1 0 36 4.00
I1 O1 0 1 0 51000 4.50
I1 O1 0 1 0 359071 0.37
I2 O2 0 1 0 13 4.00
I2 O2 0 1 0 211 .25
I3 O1 1 1 0 36 4.00
I3 O1 1 1 0 51000 4.50
I3 O1 1 2 A 36 4.00
I3 O1 1 2 A 51000 4.50
I4 O1 0 1 0 359071 6.35
I5 O4 0 1 0 6 6.00
I5 O4 0 1 0 65 0.25
I5 O4 0 1 0 AIHK0 1.00
I5 O4 0 1 0 EMBA0 0.50
I5 O4 0 1 0 EMTQ0 1.00
There can be up to 10 TAXBODY rows for each INVNUM, ORDNUM, SHIPNUM, INVLINE, CHGCODE combination. In other words, there can be up to 10 but there may be less.
Using I2 as an example, I would like the result to be:
INVNUM ORDNUM SHIPNUM INVLINE CHGCODE TAXBODY0 TAXBODY1...TAXBODY9 TAXRATE0 TAXRATE1...TAXRATE9
I2 O2 0 1 0 13 211 NULL 4.00 .25 NULL
I attempted to start small so I could test using PIVOT to get me just the tax rate and I'm getting back NULL in all the TAXRATEx columns. Here is my SQL statement I used:
SELECT * FROM (
SELECT
[invnum],
[ordnum],
[shipnum],
[taxbody],
[taxrate]
FROM #mytable
) TaxDetails
PIVOT (
AVG([taxrate])
FOR [taxbody]
IN (
[taxrate0],
[taxrate1],
[taxrate2],
[taxrate3],
[taxrate4],
[taxrate5],
[taxrate6],
[taxrate7],
[taxrate8],
[taxrate9]
)) AS PivotTable
I realize it doesn't contain everything I need for my unique combination but again, I was trying to start out small for testing purposes. When I run the query, I end up with NULL in TAXRATE0 through TAXRATE9. It also doesn't seem to matter what aggregate function I use, e.g. SUM or MAX. I've not used PIVOT before so I'm sure I'm doing something wrong.
I am requesting help figuring out why my SQL statement doesn't work and ultimately would like help, e.g. links or examples, with the following end result:
One row with 10 TAXBODY and TAXRATE columns for each INVNUM, ORDNUM, SHIPNUM, INVLINE, CHGCODE combination as mentioned above in the example.
The table should allow NULL in the TAXBODYx and TAXRATEx columns where I don't have a value, i.e. I only have 2 tax body rows out of a possible 10.
To be able to use the query or a stored procedure to update the appropriate TAXBODY and TAXRATE column(s) in a table that already exists. The existing table already supports the ability to hold values from multiple TAXBODY and TAXRATE columns.
I've found a couple examples of using PIVOT but they don't seem to work for me. I'm guessing it's because I don't understand how PIVOT works. Resources, e.g. links, would be appreciated as well as an explanation if you provide examples to help get me on the right path.
Basic Example
An example that pivots multiple columns
I think this is more in the direction you need:
Sample data:
declare #tbl table(INVNUM varchar(50), ORDNUM varchar(50), SHIPNUM varchar(50), INVLINE varchar(50), CHGCODE varchar(50), TAXBODY varchar(50), TAXRATE decimal(18,2) )
insert into #tbl
select 'I1', 'O1', '0', ' 1', ' 0', '36', '4.00'
union all select 'I1', 'O1', '0', ' 1', ' 0', '51000','4.50'
union all select 'I1', 'O1', '0', ' 1', ' 0', '359071', '0.37'
union all select 'I2', 'O2', '0', ' 1', ' 0', '13', '4.00'
union all select 'I2', 'O2', '0', ' 1', ' 0', '211', '.25'
union all select 'I3', 'O1', '1', ' 1', ' 0', '36', '4.00'
union all select 'I3', 'O1', '1', ' 1', ' 0', '51000', '4.50'
union all select 'I3', 'O1', '1', ' 2', ' A', '36', '4.00'
union all select 'I3', 'O1', '1', ' 2', ' A', '51000', '4.50'
union all select 'I4', 'O1', '0', ' 1', ' 0', '359071', '6.35'
union all select 'I5', 'O4', '0', ' 1', ' 0', '6', ' 6.00'
union all select 'I5', 'O4', '0', ' 1', ' 0', '65', '0.25'
union all select 'I5', 'O4', '0', ' 1', ' 0', 'AIHK0', '1.00'
union all select 'I5', 'O4', '0', ' 1', ' 0', 'EMBA0', '0.50'
union all select 'I5', 'O4', '0', ' 1', ' 0', 'EMTQ0', '1.00'
For a basic pivot, you need to put actual row values as column names. In your example, this is what you pivot so you have values:
SELECT * FROM (
SELECT [invnum],[ordnum],[shipnum],[taxbody],[taxrate] FROM #tbl) TaxDetails
PIVOT (AVG([taxrate]) FOR [taxbody] IN ([36],[51000],[taxrate2],[taxrate3],[taxrate4],[taxrate5],[taxrate6],[taxrate7],[taxrate8],[taxrate9])) AS PivotTable````
The 2nd link you posted basicly 'creates' 2 new columns on which to pivot data, so that you obtain nice column names.(good link btw).
SELECT [invnum],
[ordnum],
[shipnum],
max(taxrate0) as taxrate0,
max(taxrate1) as taxrate1,
max(taxrate2) as taxrate2,
max(taxrate3) as taxrate3,
max(taxrate4) as taxrate4,
max(taxrate5) as taxrate5,
max(taxbody0) as taxbody0,
max(taxbody1) as taxbody1,
max(taxbody2) as taxbody2,
max(taxbody3) as taxbody3,
max(taxbody4) as taxbody4,
max(taxbody5) as taxbody5
FROM (
SELECT
[invnum],
[ordnum],
[shipnum],
[taxbody],
[taxrate],
'taxrate'+ CAST(DENSE_RANK() OVER (PARTITION BY [invnum], [ordnum] ORDER BY taxrate ASC)-1 AS NVARCHAR) AS taxratenumber,
'taxbody'+ CAST(DENSE_RANK() OVER (PARTITION BY [invnum], [ordnum] ORDER BY taxrate ASC)-1 AS NVARCHAR) AS taxbodynumber
FROM #tbl
) TaxDetails
PIVOT (
AVG([taxrate])
FOR taxratenumber
IN ([taxrate0],[taxrate1],[taxrate2],[taxrate3],[taxrate4],[taxrate5],[taxrate6],[taxrate7],[taxrate8],[taxrate9])) AS PivotTable1
PIVOT (
max([taxBody])
FOR taxbodynumber
IN ([taxbody0],[taxbody1],[taxbody2],[taxbody3],[taxbody4],[taxbody5],[taxbody6],[taxbody7],[taxbody8],[taxbody9])) AS PivotTable2
group by invnum, ordnum, shipnum
I am implementing MS SQL query in which I need to check all conditions and get a merged result in one field(OupputField) as a string.
Table: Customer
Id Customer Type Active
------------------------
1 John 1 1
2 Bob 2 0
3 TOM 0 1
I trying to get OupputField values by checking ALL different cases. but it checks for one true condition and returns the result. I need to check all the cases and need to return combine result as OutputField
Expected Output:
Id Customer Type Active OutputField
--------------------------------------
1 John 1 1 Type1, Active
2 Bob 2 0 Type2
3 TOM 0 1 Active
MS SQL Query:
select
Id,
Customer,
TypeId
Active
COALESCE
(
CASE
WHEN TypeId = 1
THEN 'Type1'
END,
CASE
WHEN Active = 1
THEN 'Active'
END
)
from Customer
Am I doing something wrong? Please help me.
Thank you in advance.
select case when type = 0 and active = 0 then ''
when type = 0 and active = 1 then 'Active'
when type > 0 and active = 0 then 'Type' + cast(type as varchar)
when type > 0 and active = 1 then 'Type' + cast(type as varchar) + ', Active'
end as result
from your_table
CREATE TABLE #tmp(Id int, Customer varchar(20), TypeId int, Active int)
INSERT INTO #tmp (Id,Customer,TypeId,Active) VALUES(1,'John',1,1)
INSERT INTO #tmp (Id,Customer,TypeId,Active) VALUES(2,'Bob',2,0)
INSERT INTO #tmp (Id,Customer,TypeId,Active) VALUES(3,'TOM',0,1)
INSERT INTO #tmp (Id,Customer,TypeId,Active) VALUES(4,'Jim',0,0)
select Id, Customer,
TypeId
Active,
CASE WHEN TypeID >0 THEN 'TypeId' + CAST(TypeID as varchar(3)) ELSE '' END +
CASE WHEN TypeID > 0 AND Active > 0 THEN ', ' ELSE '' END +
CASE WHEN Active > 0 THEN 'Active' ELSE '' END OutputField
from #tmp
I'm writing a query to aggregate bookings for an event, and to then split the total figure into two categories: a count of those people with an application, and a count of those without an application.
Calculating the total booking figure and the number of applicants is no problem - the code I'm using is as follows:
SELECT [EVENTMODULE].[DESCRIPTION] as 'Event', cast([EVENTMODULE].[STARTDATE] as date) as 'Event Date',
SUM (case when [EVENTPLACE].[STATUS] IN ('Accepted','Attended') then 1 else 0 end) 'Total Bookings',
SUM (case when [EVENTPLACE].[STATUS] IN ('Accepted','Attended') AND [COURSEPLACE].[TYPE] = 'Application' then 1 else 0 end) 'Current Applicants' ...
However, I'm having problems with calculating the count of people that do not have an application (i.e. they have no application record associated with their account). I've tried using a NOT EXISTS statement, but discovered that this won't work within an aggregate statement.
So, what I'm instead trying to do is simply subtract the 'Number of Applicants' from the 'Total Bookings' figure, as this will leave me with a count of the number of non-applicants.
I've tried to simply subtract the above two outputs using the line of code below:
SUM ('Total Bookings' - 'Current Applicants') 'Non-Applicants'
But this gives me the error:
"Msg 8117, Level 16, State 1, Line 4
Operand data type varchar is invalid for subtract operator."
I'm presuming I need to get the earlier output to cast as an Integer - please can anyone help me with the syntax?
You can't use column aliases from your calculations directly in the same query, you could use your current SELECT as a derived table, or a CTE, or simply derive your new calculation. Also, you should avoid using single quotes for table aliases, instead use []:
SELECT [EVENTMODULE].[DESCRIPTION] as [Event],
CAST([EVENTMODULE].[STARTDATE] as DATE) as [Event Date],
SUM(CASE WHEN [EVENTPLACE].[STATUS] IN ('Accepted','Attended') THEN 1 ELSE 0 END) [Total Bookings],
SUM(CASE WHEN [EVENTPLACE].[STATUS] IN ('Accepted','Attended') AND [COURSEPLACE].[TYPE] = 'Application' THEN 1 ELSE 0 END) [Current Applicants],
SUM(CASE WHEN [EVENTPLACE].[STATUS] IN ('Accepted','Attended') AND ISNULL([COURSEPLACE].[TYPE],'') <> 'Application' THEN 1 ELSE 0 END) [Non-Applicants]
...
Use Square Brackets to escape the space in column names. Single quotes will make it as string constant
select SUM ([Total Bookings] - [Current Applicants]) 'Non-Applicants'
from
(
SELECT [EVENTMODULE].[DESCRIPTION] as 'Event', cast([EVENTMODULE].[STARTDATE] as date) as 'Event Date',
SUM (case when [EVENTPLACE].[STATUS] IN ('Accepted','Attended') then 1 else 0 end) 'Total Bookings',
SUM (case when [EVENTPLACE].[STATUS] IN ('Accepted','Attended') AND [COURSEPLACE].[TYPE] = 'Application' then 1 else 0 end) 'Current Applicants'
..
)
Note : When you are using Single quotes to escape the space in alias name it will work but it will not work when using it as column names
Hope this helps
with cte as
(
SELECT [EVENTMODULE].[DESCRIPTION] as 'Event', cast([EVENTMODULE].[STARTDATE] as date) as 'Event Date',
SUM (case when [EVENTPLACE].[STATUS] IN ('Accepted','Attended') then 1 else 0 end) 'Total Bookings',
SUM (case when [EVENTPLACE].[STATUS] IN ('Accepted','Attended') AND [COURSEPLACE].[TYPE] = 'Application' then 1 else 0 end)
)
select Event,Event Date,Total Bookings,[Total Bookings]-[EVENTPLACE].[STATUS] AS 'Non-Applicants'
from cte
Try this:
SELECT * , [Non-Applicants] = [Total Bookings] - [Current Applicants]
FROM
(
SELECT [EVENTMODULE].[DESCRIPTION] as 'Event', cast([EVENTMODULE].[STARTDATE] as date) as 'Event Date',
SUM (case when [EVENTPLACE].[STATUS] IN ('Accepted','Attended') then 1 else 0 end) 'Total Bookings',
SUM (case when [EVENTPLACE].[STATUS] IN ('Accepted','Attended') AND [COURSEPLACE].[TYPE] = 'Application' then 1 else 0 end) 'Current Applicants' ...
) A
Using SQL Server 2012, I have the following table
CREATE TABLE [dbo].[DataField](
[DisplayName] [varchar](255) NOT NULL,
[DisplayValue] [varchar](255) NOT NULL
) ON [PRIMARY]
GO
I run this insert query
INSERT INTO dbo.DataField VALUES
('Column 1', '10'),
('Column 2', '20'),
('Column 1', '30'),
('Column 2', '40'),
('Column 1', '50'),
('Column 2', '60'),
('Column 1', '70'),
('Column 2', '80')
I run this query...
SELECT DisplayName, DisplayValue FROM [dbo].[DataField]
Which returns
Field | Value
'Column 1' | 10
'Column 2' | 20
'Column 1' | 30
'Column 2' | 40
'Column 1' | 50
'Column 2' | 60
I would like to write a query that outputs the results like this..
Column 1 | Column 2
10 | 20
30 | 40
50 | 60
Can I do this using Pivot or Unpivot or some other tsql?
In #BogdanSahlean's answer, instead of row_number you may also use dense_rank like:
SELECT z.[Column A], z.[Column B]
FROM (
SELECT x.DisplayName, x.DisplayValue, x.GroupNum
FROM (
SELECT *
, (DENSE_RANK()
OVER(PARTITION BY df.DisplayName
ORDER BY df.DataFieldID)) AS GroupNum
FROM #t df
) x
) y
PIVOT( MAX(y.DisplayValue) FOR y.DisplayName IN ([Column A], [Column B]) ) z;