SQL Pivot/Transform - sql-server

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;

Related

Concat column values based on other columns groups - each column from different table

I am trying to write a query in SQL that will bring me a table with columns from different tables and in one column I want to concat the values based on groups from the other columns.
my data is like
And I want this outcome
The 3 columns are from different tables and I have only read access to the database.
This is a pretty straightforward request using STRING_AGG (requires SQL Server 2017 (14.x)+).
Run the below in SSMS.
DECLARE #data table ( Program varchar(20), Subprogram varchar(20), Region varchar(20) );
INSERT INTO #data VALUES
( 'program 1', 'subprogram 1', 'Region 1' ),
( 'program 1', 'subprogram 1', 'Region 2' ),
( 'program 1', 'subprogram 1', 'Region 3' ),
( 'program 1', 'subprogram 1', 'Region 4' ),
( 'program 2', 'subprogram 2', 'Region 5' );
SELECT
Program, Subprogram, STRING_AGG ( Region, ',' ) AS Region
FROM #data
GROUP BY
Program, Subprogram
ORDER BY
Program, Subprogram, Region;
Returns
+-----------+--------------+-------------------------------------+
| Program | Subprogram | Region |
+-----------+--------------+-------------------------------------+
| program 1 | subprogram 1 | Region 1,Region 2,Region 3,Region 4 |
| program 2 | subprogram 2 | Region 5 |
+-----------+--------------+-------------------------------------+

SSRS 100% Stacked Bar - Group on Field Names to show totals

I am trying to create a 100% stacked bar chart to display totals I have of various counts I'm getting through a query. I cannot figure out how to use the grouping the allow the y axis of the chart to display the different column names of the totals I have. I have created what I want in separate charts but because the way html formats everything there is a bunch of unwanted spacing and I'm trying to create this in one chart. Example below
In this I am just getting the sum of the column I have which is returning a 1 or 0 for each item based on the status. Then for the remaining 100% I'm using an expression to subtract them from a total.
=Sum(Count(Fields!Computer_Name.Value)) - Sum(Fields!ClientHealthEvaluation.Value)
I can modify my query to group all this in the results and just have a query of the totals but I still haven't found a way to make that work in one bar chart either. I would like to know if there is a way to have all this displayed in one bar chart, y axis groups are the separate columns, bars showing the totals so its cleaner or at least to know of a better way to structure all these separate charts in the image so they look more uniform. Is this possible?
--Edit - Adding sample of dataset
resourceID IsActiveDDR IsActivePolicyRequest IsActiveStatusMessages IsActiveHW IsActiveSW ClientHealthEvaluation
16784171 0 0 0 0 0 1
16784668 1 1 1 1 0 1
16784901 0 0 0 0 0 1
16785366 1 0 1 0 0 1
16786781 0 0 0 0 0 1
16786855 0 0 0 0 0 1
16787070 1 1 1 0 0 1
16787571 0 0 0 0 0 1
16787996 1 1 1 1 0 0
16788182 1 1 1 1 0 1
This is the data i currently have and i use sum function on each column to get the totals. I can group this like below if its easier.
Total IsActiveDDR IsActivePolicyRequest IsActiveStatusMessages IsActiveHW IsActiveSW ClientHealthEvaluation
10 5 4 5 3 0 9
---Edit: Updated dataset as suggested to now format the table in a way that will work better with a chart.
select
'Client Health Evaluation' as 'PolicyType',
'Success' as 'Status',
SUM(a.ClientHealthEvaluation) as 'Amount'
from(
Select
summ.Resourceid,
case summ.LastEvaluationHealthy when 1 then 1 else 0 end as 'ClientHealthEvaluation'
from v_CH_ClientSummary summ) a
UNION
select
'Client Health Evaluation' as 'PolicyType',
'Failure' as 'Status',
(Count(a.resourceid) - SUM(a.ClientHealthEvaluation)) as 'Amount'
from(
Select
summ.Resourceid,
case summ.LastEvaluationHealthy when 1 then 1 else 0 end as 'ClientHealthEvaluation'
from v_CH_ClientSummary summ) a
-------------
UNION
select
'Policy Request' as 'PolicyType',
'Success' as 'Status',
SUM(a.IsActivePolicyRequest) as 'Amount'
from(
Select
summ.Resourceid,
summ.IsActivePolicyRequest
from v_CH_ClientSummary summ) a
UNION
select
'Policy Request' as 'PolicyType',
'Failure' as 'Status',
(Count(a.resourceid) - SUM(a.IsActivePolicyRequest)) as 'Amount'
from(
Select
summ.Resourceid,
summ.IsActivePolicyRequest
from v_CH_ClientSummary summ) a
-------------
UNION
select
'Data Discovery' as 'PolicyType',
'Success' as 'Status',
SUM(a.IsActiveDDR) as 'Amount'
from(
Select
summ.Resourceid,
summ.IsActiveDDR
from v_CH_ClientSummary summ) a
UNION
select
'Data Discovery' as 'PolicyType',
'Failure' as 'Status',
(Count(a.resourceid) - SUM(a.IsActiveDDR)) as 'Amount'
from(
Select
summ.Resourceid,
summ.IsActiveDDR
from v_CH_ClientSummary summ) a
-------------
UNION
select
'Hardware Inventory' as 'PolicyType',
'Success' as 'Status',
SUM(a.IsActiveHW) as 'Amount'
from(
Select
summ.Resourceid,
summ.IsActiveHW
from v_CH_ClientSummary summ) a
UNION
select
'Hardware Inventory' as 'PolicyType',
'Failure' as 'Status',
(Count(a.resourceid) - SUM(a.IsActiveHW)) as 'Amount'
from(
Select
summ.Resourceid,
summ.IsActiveHW
from v_CH_ClientSummary summ) a
-------------
UNION
select
'Software Inventory' as 'PolicyType',
'Success' as 'Status',
SUM(a.IsActiveSW) as 'Amount'
from(
Select
summ.Resourceid,
summ.IsActiveSW
from v_CH_ClientSummary summ) a
UNION
select
'Software Inventory' as 'PolicyType',
'Failure' as 'Status',
(Count(a.resourceid) - SUM(a.IsActiveSW)) as 'Amount'
from(
Select
summ.Resourceid,
summ.IsActiveSW
from v_CH_ClientSummary summ) a
-------------
UNION
select
'Status Messages' as 'PolicyType',
'Success' as 'Status',
SUM(a.IsActiveStatusMessages) as 'Amount'
from(
Select
summ.Resourceid,
summ.IsActiveStatusMessages
from v_CH_ClientSummary summ) a
UNION
select
'Status Messages' as 'PolicyType',
'Failure' as 'Status',
(Count(a.resourceid) - SUM(a.IsActiveStatusMessages)) as 'Amount'
from(
Select
summ.Resourceid,
summ.IsActiveStatusMessages
from v_CH_ClientSummary summ) a
Order by PolicyType, Status desc
Output:
PolicyType Status Amount
ClientHealth Evaluation Success 13862
Client Health Evaluation Failure 210
Data Discovery Success 13967
Data Discovery Failure 105
Hardware Inventory Success 13854
Hardware Inventory Failure 218
Policy Request Success 14025
Policy Request Failure 47
Software Inventory Success 13713
Software Inventory Failure 359
Status Messages Success 14018
Status Messages Failure 54
Chart:
If this does not help, please edit your question and include a sample of your base data and dataset output.
I created some sample data as follows - I think this is where yo might need to make a change, by calculating this in your dataset query but until I see your data its hard to tell.
Anyway, here i sthe sample data
DECLARE #t TABLE(Caption varchar(30), Colour varchar(10), Amount int)
INSERT INTO #t VALUES
('Client Health Evaluation', 'Green', 10),
('Client Health Evaluation', 'Red', 1),
('Policy Request', 'Green', 12),
('Policy Request', 'Red', 3),
('Data Discovery', 'Green', 15),
('Data Discovery', 'Red', 2),
('Hardware Inventory', 'Green', 20),
('Hardware Inventory', 'Red', 2),
('Software Inventory', 'Green', 30),
('Software Inventory', 'Red', 5),
('Status Messages', 'Green', 10),
('Status Messages', 'Red', 2)
SELECT * FROM #t
Then I simply added a 100% bar chart and configured it like this...
All I did was drag the fields into the respective bins 'Values'/'Category Groups'/'Series Groups' and added a bit of colour formatting.
Which gives the following output.
EDIT using example data
I've taken you table (again just as a table variable so just swap out #t for the real table name.
I then unpivot the data inside a CTE so I can reference it more than once, then UNION two copies of the data, one is the actual values and one is the values subtracted from the record count to give you the "red" values.
DECLARE #t TABLE (resourceID bigint, IsActiveDDR int, IsActivePolicyRequest int, IsActiveStatusMessages int, IsActiveHW int , IsActiveSW int, ClientHealthEvaluation int)
INSERT INTO #t VALUES
(16784171, 0, 0, 0, 0, 0, 1),
(16784668, 1, 1, 1, 1, 0, 1),
(16784901, 0, 0, 0, 0, 0, 1),
(16785366, 1, 0, 1, 0, 0, 1),
(16786781, 0, 0, 0, 0, 0, 1),
(16786855, 0, 0, 0, 0, 0, 1),
(16787070, 1, 1, 1, 0, 0, 1),
(16787571, 0, 0, 0, 0, 0, 1),
(16787996, 1, 1, 1, 1, 0, 0),
(16788182, 1, 1, 1, 1, 0, 1);
-- SELECT * from #t
-- UNPIVOT THE DATA
WITH nd (caption, FlagSum, RecordCount) AS
(
SELECT caption, SUM(flag) AS flagCount, (SELECT COUNT(*) FROM #t) AS TCount
FROM
(SELECT IsActiveDDR, IsActivePolicyRequest, IsActiveStatusMessages, IsActiveHW, IsActiveSW, ClientHealthEvaluation FROM #t) p
UNPIVOT
(flag FOR caption
IN (IsActiveDDR, IsActivePolicyRequest, IsActiveStatusMessages, IsActiveHW, IsActiveSW, ClientHealthEvaluation)
) unpiv
GROUP BY caption
)
SELECT caption, 'Green' as SeriesGroup, FlagSum FROM nd
UNION ALL
SELECT caption, 'Red', RecordCount - FlagSum FROM nd
This give us the following results
You should be able to drop this straight onto your chart as per this answer above.

PIVOT returns NULL When Converting Rows to Columns

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

How to multi-select filter an EAV table in SQL Server

I have an EAV table with attributes and would like to do a hybrid selection of the items based on variables that are passed into a stored procedure.
Sample table:
| group_id | item_id | key | value |
+----------+---------+--------+-------+
| 1 | AA | length | 10 |
| 1 | AA | width | 10 |
| 1 | AA | color | white |
| 1 | AA | brand | beta |
| 1 | BB | length | 25 |
| 1 | BB | brand | alpha |
| 2 | CC | brand | alpha |
Sample query:
declare #attributes nvarchar(max) = 'brand name, length'
declare #attributeValues nvarchar(max) = 'alpha, beta, 25'
declare #id int = 1
select *
into #allProductsFromGroup
from items
where group_id = #id
select item_id
from #allProductsFromGroup #all
where [key] in (select value from string_split(#attributes, ','))
and [value] in (select value from string_split(#attributeValues, ','))
Expected output:
| item_id |
+---------+
| BB |
I could hard-code in and and or statements for each key, but there are many, and I am looking for a more scalable solution.
Passing in and parsing JSON would be good, like:
[
{ "brand": "aplha" },
{ "brand": "beta" },
{ "length": 25 }
]
How can I write the second select to dynamically return a subset of allProductsFromGroup that dynamically include multiple results from the same group (multi-select brand or multi-select length), but exclude from other groups (color, length, etc.)?
The target query might look something like this:
with q as
(
select item_id,
max( case when [key] = 'brand' then [value] end ) brand,
max( case when [key] = 'length' then cast( [value] as int ) end ) length,
from #allProductsFromGroup
group by Item_id
)
select item_id
from q
where brand in ('alpha','beta') and length=25
You just have to build it from the incoming data (yuck). A simpler query form to generate might be something like
select item_id
from #allProductsFromGroup
where [key] = 'brand' and [value] in ('alpha','beta')
intersect
select item_id
from #allProductsFromGroup
where [key] = 'length' and [value] = 25
mapping and criteria to intersect, and or criteria to union. It's likely to be cheaper too, as each query can seek an index on (key,value).
It's probably a late answer, but if you can pass conditions as JSON, the next approach is also a possible solution. The JSON must be in the same format as in the answer and you may use more than two conditions:
Table:
CREATE TABLE Data (
group_id int,
item_id varchar(2),
[key] varchar(100),
[value] varchar(100)
)
INSERT INTO Data (group_id, item_id, [key], [value])
VALUES
(1, 'AA', 'length', '10'),
(1, 'AA', 'width', '10'),
(1, 'AA', 'color', 'white'),
(1, 'AA', 'brand', 'beta'),
(1, 'BB', 'length', '25'),
(1, 'BB', 'brand', 'alpha'),
(2, 'CC', 'brand', 'alpha')
Conditions as JSON:
DECLARE #conditions varchar(max) = N'
[
{"key": "brand", "values": ["alpha", "beta"]},
{"key": "length", "values": ["25"]}
]
'
Statement:
SELECT d.item_id
FROM Data d
JOIN (
SELECT j1.[key], j2.[value]
FROM OPENJSON(#conditions) WITH (
[key] varchar(100) '$.key',
[values] nvarchar(max) '$.values' AS JSON
) j1
CROSS APPLY OPENJSON(j1.[values]) j2
) o ON d.[key] = o.[key] AND d.[value] = o.[value]
GROUP BY d.item_id
HAVING COUNT(*) = (SELECT COUNT(*) FROM OPENJSON(#conditions))
Result:
item_id
BB

SQL Server 2008 R2 Dynamic Pivot Query with bit types

I have four tables that contain data that used as part of a output that will be defined below
[Status]
StatusId INT
IsFinish BIT
[Type]
TypeId INT
TypeName VARCHAR
IsWorkflow BIT
[System]
SystemId INT
SystemName VARCHAR
[Track]
TrackId INT
StatusId INT (FK)
TypeId INT (FK)
SystemId INT (FK)
The desired output format would like this:
SystemName | TypeName1 | TypeName2 | TypeNameN
SystemName | IsFinish | IsFinish | IsFinish
Notes:
IsFinish would display 0/1
TypeName1, TypeName2, TypeNameN is the text value of [Type].TypeName
Result are filtered to only where [Type].IsWorkflow = 1.
This is running on SQL Server 2008 R2
Here is sample data:
[Status]
StatusId, IsFinish
10, 1
11, 1
12, 0
[Type]
TypeId, TypeName, IsWorkflow
101, 'Type A', 1
102, 'Type B', 1
103, 'Type C', 0
104, 'Type D', 1
[System]
SystemId, SystemName
1001, 'System 1'
1002, 'System 2'
1003, 'System 3'
[Track]
TrackId, StatusId, TypeId, SystemId
20001, 10, 101, 1001
20002, 10, 102, 1001
20003, 12, 101, 1002
20004, 11, 101, 1003
20005, 10, 102, 1003
20006, 12, 103, 1003
Desired output sample:
System Name | Type A | Type B
System 1 | 1 | 0
System 2 | 0 | <NULL>
System 3 | 1 | 0
Notes on output sample:
"Type C" column isn't listed because IsWorkflow = 0
"Type D" column isn't listed because no Tracks have that type
I took a stab at the syntax based on examples I found:
SELECT T.*
FROM [Type] T INNER JOIN [Track] TR ON T.TypeId = TR.TypeId
INNER JOIN [System] S ON S.SystemId = TR.SystemId
INNER JOIN [Status] ST ON ST.StatusId = TR.StatusId
PIVOT ( IsFinish FOR TypeName IN (*)) AS Workflow
WHERE AND IsWorkflow = 1 AND Status = 11
There are number of issues with this syntax:
It seems Pivot wants an aggregate summary function, opposed to displaying just displaying value
The column names need to static, wildcard is not supported.
My questions:
Is PIVOT the right choice for what I'm trying to accomplish? If so, how should I update my syntax?
What would be a better approach?
You could do this using a Dynamic Crosstab. See this great article by Jeff Moden for reference.
SQL Fiddle
DECLARE #sql1 VARCHAR(4000) = ''
DECLARE #sql2 VARCHAR(4000) = ''
DECLARE #sql3 VARCHAR(4000) = ''
SELECT #sql1 =
'SELECT
s.SystemName' + CHAR(10)
SELECT #sql2 = #sql2 +
' , MAX(CASE WHEN t.TypeId = '+ CONVERT(VARCHAR(5),t.TypeId) + ' THEN CAST(st.IsFinish AS INT) END) AS [' + t.TypeName + '],' + CHAR(10)
FROM(
SELECT t.*
FROM Type t
WHERE
t.IsWorkflow = 1
AND EXISTS(SELECT 1 FROM Track WHERE TypeId = t.TypeId)
)t
SELECT #sql3 =
'FROM System s
INNER JOIN Track t ON t.SystemId = s.SystemId
INNER JOIN Status st ON st.StatusId = t.StatusId
GROUP BY s.SystemName'
PRINT(#sql1 + #sql2 + #sql3)
EXEC(#sql1 + #sql2 + #sql3)

Resources