Get Pivot values on specific condition - sql

I have query in SQL SEVRER -
SELECT alarm,annual_calendar,chronograph,day_flag,equation_of_time,flyback_chronograph,
gmt_time,jumping_hour,minute_repeater,moon_phase,perpetual_calendar,power_reserve,seconds_flag
,split_seconds_chrono,tachymeter,tourbillon,ultra_thin,world_time,catalog_item_id
FROM catalog_item_watches where alarm is not null
order by id desc
which return output like
And i want result like
Thanks in advance.

First make UNPIVOT, then exclude the N values. After that make a PIVOT. You may want to make it dynamic.
It should be something like this:
SELECT *
FROM
(
SELECT [catalog_item_id]
,[column]
,'Web' + CAST(DENSE_RANK() OVER(PARTITION BY [catalog_item_id] ORDER BY [column]) AS VARCHAR(12))
FROM
(
SELECT [catalog_item_id], [alarm], [annual_calendar], [chronograph], [day_flag], [equation_of_time], [flyback_chronograph], [ gmt_time], [jumping_hour], [minute_repeater], [moon_phase], [perpetual_calendar], [power_reserve], [seconds_flag], [split_seconds_chrono], [tachymeter], [tourbillon], [ultra_thin], [world_time]
FROM catalog_item_watches
where [alarm] is not null
) DS
UNPIVOT
(
[value] FOR [column] IN ([alarm], [annual_calendar], [chronograph], [day_flag], [equation_of_time], [flyback_chronograph], [ gmt_time], [jumping_hour], [minute_repeater], [moon_phase], [perpetual_calendar], [power_reserve], [seconds_flag], [split_seconds_chrono], [tachymeter], [tourbillon], [ultra_thin], [world_time])
) UNPVT
WHERE UNPVT.[value] = 'Y'
) DataSource ([catalog_item_id], [column_value], [column_name])
PIVOT
(
MAX([column_value]) FOR [column_name] IN ([web1], [web2], [web3], [web4], [web5], [web6], [web7], [web8], [web9], [web10], [web11], [web12], [web13], [web14], [web15], [web16], [web17], [web18])
) PVT

Related

Add new column in the dynamic query

This a dynamic query and it is showing as a table. But I want to ad a column in this query as 'header' as identifier. The dynamic query is below:
SELECT [YR_4]
,[YR_3]
,[YR_2]
,[YR_1]
FROM (
SELECT CASE
WHEN yr = 9999
THEN 'A Medians'
ELSE cast(yr AS VARCHAR(10))
END AS yr
,yrdes
FROM #years2
) AS t
PIVOT(MAX(yr) FOR yrdes IN (
[YR_4]
,[YR_3]
,[YR_2]
,[YR_1]
)) t1
Can somebody help me to add a column with hardcoded value in the above query?
You can have a additional column with hardcoded value as given below:
SELECT [YR_4]
,[YR_3]
,[YR_2]
,[YR_1]
,'Hardcoded_value' AS AdditionalColum -- Code change here
FROM (
SELECT CASE
WHEN yr = 9999
THEN 'A Medians'
ELSE cast(yr AS VARCHAR(10))
END AS yr
,yrdes
FROM #years2
) AS t
PIVOT(MAX(yr) FOR yrdes IN (
[YR_4]
,[YR_3]
,[YR_2]
,[YR_1]
)) t1
You seems want sub-query :
select 'header' as custom_col, t.*
from ( <dynamic query>
) t;
You can also use temporary table :
SELECT [YR_4, [YR_3], [YR_2], [YR_1] INTO #Temptable
FROM (SELECT CASE WHEN yr = 9999
THEN 'A Medians'
ELSE cast(yr AS VARCHAR(10))
END AS yr, yrdes
FROM #years2
) AS t
PIVOT ( MAX(yr) FOR yrdes IN ([YR_4], [YR_3], [YR_2], [YR_1] )
) t1;

SQL need to add outerjoin to the query below

In the below SQL:
I need to add two columns in the result
1) Local_code
2)Local_CPTY_SYS_ID,
which are in HSBC_LOCAL_INVOL_PARTY table.
So far I have tried to add
select local_code from HSBC_LOCAL_INVOL_PARTY
h join t_cdr T2
on T2.counterparty_new = h.entity_code
but that doesn't work. It needs an explicit outer join in the end. Please help
SELECT
T2.counterparty_new,
T2.bis_entity_type_original,
T2.counterparty_new_desc,
T2.counterparty_new_attribute_6,
T2.method_original,
T2.netting_agreement_reference,
T2.internal_rating_new,
T2.counterparty_type_original,
T2.obligor_grade_new,
T2.pd_pre_floor_new,
T2.pd_new,
T2.lgd,
T2.rwa
from t_cdr T2,
(
SELECT * FROM (
SELECT
FINAL.FILTER_MARKER,
FINAL.entity_code
FROM (
SELECT
FILTER_POP.entity_code,
FILTER_POP.FILTER_MARKER
FROM (
SELECT
CASE
WHEN CONCAT(Dlgd,unfloored_lgd) IS NOT NULL
THEN 'EXCLUDE'
WHEN CONCAT(Dlgd,unfloored_lgd) IS NULL
THEN 'INCLUDE'
END AS FILTER_MARKER,
entity_code,
Dlgd,
unfloored_lgd
FROM
HSBC_LOCAL_INVOL_PARTY
WHERE
((HSBC_LOCAL_INVOL_PARTY.entity_code) NOT LIKE '%DUM%')
AND
((HSBC_LOCAL_INVOL_PARTY.entity_code) NOT LIKE '%HSBC%')
) FILTER_POP
GROUP BY
FILTER_POP.entity_code,
FILTER_POP.FILTER_MARKER) FINAL
GROUP BY
FINAL.FILTER_MARKER,
FINAL.entity_code
ORDER BY
FINAL.entity_code)
PIVOT
(
COUNT(FILTER_MARKER)
FOR FILTER_MARKER IN ('INCLUDE' AS INCLUDE,'EXCLUDE' AS EXCLUDE)
)
WHERE INCLUDE = 1 AND EXCLUDE = 0
) ENTITY_FILTER
WHERE ENTITY_FILTER.entity_code = T2.counterparty_new
AND T2.method_original = 'ADV'
ORDER BY T2.rwa DESC
Solved it: Look at the last few lines. Took a while but optimized it as well for performance.
SELECT
T2.counterparty_new,
T2.bis_entity_type_original,
T2.counterparty_new_desc,
T2.counterparty_new_attribute_6,
T2.method_original,
T2.netting_agreement_reference,
T2.internal_rating_new,
T2.counterparty_type_original,
T2.obligor_grade_new,
T2.pd_pre_floor_new,
T2.pd_new,
T2.lgd,
HSBC_LOCAL_INVOL_PARTY.local_code,
T2.rwa
from t_cdr T2,
(
SELECT * FROM (
SELECT
FINAL.FILTER_MARKER,
FINAL.entity_code
FROM (
SELECT
FILTER_POP.entity_code,
FILTER_POP.FILTER_MARKER
FROM (
SELECT
CASE
WHEN CONCAT(Dlgd,unfloored_lgd) IS NOT NULL
THEN 'EXCLUDE'
WHEN CONCAT(Dlgd,unfloored_lgd) IS NULL
THEN 'INCLUDE'
END AS FILTER_MARKER,
entity_code,
Dlgd,
unfloored_lgd
FROM
HSBC_LOCAL_INVOL_PARTY
WHERE
((HSBC_LOCAL_INVOL_PARTY.entity_code) NOT LIKE '%DUM%')
AND
((HSBC_LOCAL_INVOL_PARTY.entity_code) NOT LIKE '%HSBC%')
) FILTER_POP
GROUP BY
FILTER_POP.entity_code,
FILTER_POP.FILTER_MARKER) FINAL
GROUP BY
FINAL.FILTER_MARKER,
FINAL.entity_code
ORDER BY
FINAL.entity_code)
PIVOT
(
COUNT(FILTER_MARKER)
FOR FILTER_MARKER IN ('INCLUDE' AS INCLUDE,'EXCLUDE' AS EXCLUDE)
)
WHERE INCLUDE = 1 AND EXCLUDE = 0
) ENTITY_FILTER,HSBC_LOCAL_INVOL_PARTY
WHERE ENTITY_FILTER.entity_code = T2.counterparty_new
AND ENTITY_FILTER.entity_code = HSBC_LOCAL_INVOL_PARTY.entity_code(+)
AND T2.method_original = 'ADV'
ORDER BY T2.rwa DESC

SQL Server use union all and paging

How to apply paging when we are using union all to get result from two tables.below is the code here i am getting duplicate values in 'row_num' column which has been used for paging.
;WITH resultSetCTE AS
(
SELECT
ROW_NUMBER() OVER
(
ORDER BY nr.is_read,nr.is_read_cashier,
CASE #columnSortNameDirection WHEN 'Pin' THEN r.name END ASC,
CASE #columnSortNameDirection WHEN 'PinDesc' THEN r.firstname END DESC
) AS 'row_num',
r.clave_receiver AS 'Pin',
r.id_branch AS 'Id_Branch',
r.id_receiver AS 'Id_receiver',
s.name_sender AS 'SenderFullName',
r.name_receiver AS 'ReceiverFullName',
r.id_flag_receiver AS 'Status',
pas.option_name AS 'ApprovalStatus',
r.mode_pay_receiver AS 'PaymentModeId'
UNION ALL
SELECT
ROW_NUMBER() OVER
(
ORDER BY nr.is_read,nr.is_read_cashier,
CASE #columnSortNameDirection WHEN 'Pin' THEN r.name END ASC,
CASE #columnSortNameDirection WHEN 'PinDesc' THEN r.firstname END DESC
) AS 'row_num',
r.clave_receiver AS 'Pin',
r.id_branch AS 'Id_Branch',
r.id_receiver AS 'Id_receiver',
s.name_sender AS 'SenderFullName',
r.name_receiver AS 'ReceiverFullName',
r.id_flag_receiver AS 'Status',
pas.option_name AS 'ApprovalStatus',
r.mode_pay_receiver AS 'PaymentModeId'
)
SELECT *,
(SELECT COUNT(1) FROM resultSetCTE) AS 'RecordCount'
FROM resultSetCTE
WHERE row_num BETWEEN (1 - 1) * 15 + 1 AND 1 * 15
ORDER by IsRead,IsReadCashier
Please use offset / fetch instead. It solves all your problems.
More info here: https://technet.microsoft.com/en-us/library/gg699618(v=sql.110).aspx
Code example (please update by your needs):
;WITH [resultSetCTE] AS
(
SELECT
[col] = [object_id]
FROM
[sys].[tables]
UNION ALL
SELECT
[col] = [object_id]
FROM
[sys].[tables]
)
SELECT
*
FROM
[resultSetCTE]
ORDER BY
[col]
OFFSET 10 ROWS FETCH NEXT 20 ROWS ONLY;
though you haven't posted the complete query, you could try something like this
declare #columnSortNameDirection varchar(5)
;WITH resultSetCTE AS
(
select ROW_NUMBER() OVER
(
ORDER BY nr.is_read,nr.is_read_cashier,
CASE #columnSortNameDirection WHEN 'Pin' THEN r.name END ASC,
CASE #columnSortNameDirection WHEN 'PinDesc' THEN r.firstname END DESC
) AS 'row_num',* from ( SELECT
r.clave_receiver AS 'Pin',
r.id_branch AS 'Id_Branch',
r.id_receiver AS 'Id_receiver',
s.name_sender AS 'SenderFullName',
r.name_receiver AS 'ReceiverFullName',
r.id_flag_receiver AS 'Status',
pas.option_name AS 'ApprovalStatus',
r.mode_pay_receiver AS 'PaymentModeId'
UNION ALL
SELECT
r.clave_receiver AS 'Pin',
r.id_branch AS 'Id_Branch',
r.id_receiver AS 'Id_receiver',
s.name_sender AS 'SenderFullName',
r.name_receiver AS 'ReceiverFullName',
r.id_flag_receiver AS 'Status',
pas.option_name AS 'ApprovalStatus',
r.mode_pay_receiver AS 'PaymentModeId') as A
)
Select *,
(SELECT COUNT(1) FROM resultSetCTE) AS 'RecordCount'
FROM resultSetCTE
WHERE row_num BETWEEN (1 - 1) * 15 + 1 AND 1 * 15
ORDER by IsRead,IsReadCashier

Using pivot table with column and row totals in sql server 2008

I have a table with following columns
defect_id, developer_name, status, summary, root_cause,
Secondary_RC, description, Comments, environment_name
The column root_cause has Enviro, Requi, Dev, TSc, TD, Unkn as its values and
column environment_name has QA1, QA2, QA3
I need to prepare a report in the below format
Enviro Requi Dev TSc TD Unkn Total
QA1 9 1 14 17 2 3 46
QA2 8 1 14 0 5 1 29
QA3 1 1 7 0 0 1 10
Total 18 3 35 17 7 5 85
I have prepare the report till
Enviro Requi Dev TSc TD Unkn
QA1 9 1 14 17 2 3
QA2 8 1 14 0 5 1
QA3 1 1 7 0 0 1
I used the below query to get the above result
select *
from
(
select environment_name as " ", value
from test1
unpivot
(
value
for col in (root_cause)
) unp
) src
pivot
(
count(value)
for value in ([Enviro] , [Requi] , [Dev] , [Tsc], [TD] , [Unkn])
) piv
Can anyone help to get the totals for columns and rows?
There may be various approaches to this. You can calculate all the totals after the pivot, or you can get the totals first, then pivot all the results. It is also possible to have kind of middle ground: get one kind of the totals (e.g. the row-wise ones), pivot, then get the other kind, although that might be overdoing it.
The first of the mentioned approaches, getting all the totals after the pivot, could be done in a very straightforward way, and the only thing potentially new to you in the below implementation might be GROUP BY ROLLUP():
SELECT
[ ] = ISNULL(environment_name, 'Total'),
[Enviro] = SUM([Enviro]),
[Requi] = SUM([Requi]),
[Dev] = SUM([Dev]),
[Tsc] = SUM([Tsc]),
[TD] = SUM([TD]),
[Unkn] = SUM([Unkn]),
Total = SUM([Enviro] + [Requi] + [Dev] + [Tsc] + [TD] + [Unkn])
FROM (
SELECT environment_name, root_cause
FROM test1
) s
PIVOT (
COUNT(root_cause)
FOR root_cause IN ([Enviro], [Requi], [Dev], [Tsc], [TD], [Unkn])
) p
GROUP BY
ROLLUP(environment_name)
;
Basically, the GROUP BY ROLLUP() part produces the Total row for you. The grouping is first done by environment_name, then the grand total row is added.
To do just the opposite, i.e. get the totals prior to pivoting, you could employ GROUP BY CUBE() like this:
SELECT
[ ] = environment_name,
[Enviro] = ISNULL([Enviro], 0),
[Requi] = ISNULL([Requi] , 0),
[Dev] = ISNULL([Dev] , 0),
[Tsc] = ISNULL([Tsc] , 0),
[TD] = ISNULL([TD] , 0),
[Unkn] = ISNULL([Unkn] , 0),
Total = ISNULL(Total , 0)
FROM (
SELECT
environment_name = ISNULL(environment_name, 'Total'),
root_cause = ISNULL(root_cause, 'Total'),
cnt = COUNT(*)
FROM test1
WHERE root_cause IS NOT NULL
GROUP BY
CUBE(environment_name, root_cause)
) s
PIVOT (
SUM(cnt)
FOR root_cause IN ([Enviro], [Requi], [Dev], [Tsc], [TD], [Unkn], Total)
) p
;
Both methods can be tested and played with at SQL Fiddle:
Method 1
Method 2
Note. I've omitted the unpivoting step in both suggestions because unpivoting a single column seemed clearly redundant. If there's more to it, though, adjusting either of the queries should be easy.
You can find Total for root_cause and environment_name using ROLLUP.
RNO_COLTOTAL - Logic to place Total in last column, since the columns Tsc,Unkn will overlap the column Total when pivoting, since its ordering alphabetically.
RNO_ROWTOTAL - Logic to place Total in last row since a value that is starting with U,W,X,Y,Z can overlap the value Total, since its ordering alphabetically.
SUM(VALUE) - Can define on what aggregate function we can use with ROLLUP.
QUERY 1
SELECT CASE WHEN root_cause IS NULL THEN 1 ELSE 0 END RNO_COLTOTAL,
CASE WHEN environment_name IS NULL THEN 1 ELSE 0 END RNO_ROWTOTAL,
ISNULL(environment_name,'Total')environment_name,
ISNULL(root_cause,'Total')root_cause,
SUM(VALUE) VALUE
INTO #NEWTABLE
FROM
(
-- Find the count for environment_name,root_cause
SELECT DISTINCT *,COUNT(*) OVER(PARTITION BY environment_name,root_cause)VALUE
FROM #TEMP
)TAB
GROUP BY root_cause,environment_name
WITH CUBE
We will get the following logic when CUBE is used
We declare variables for pivoting.
#cols - Column values for pivoting.
#NulltoZeroCols - Replace null values with zero.
QUERY 2
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + root_cause + ']',
'[' + root_cause + ']')
FROM (SELECT DISTINCT RNO_COLTOTAL,root_cause FROM #NEWTABLE) PV
ORDER BY RNO_COLTOTAL,root_cause
DECLARE #NulltoZeroCols NVARCHAR (MAX)
SET #NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+root_cause+'],0) AS ['+root_cause+']'
FROM(SELECT DISTINCT RNO_COLTOTAL,root_cause FROM #NEWTABLE GROUP BY RNO_COLTOTAL,root_cause)TAB
ORDER BY RNO_COLTOTAL FOR XML PATH('')),2,8000)
Now pivot it dynamically
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT environment_name,'+ #NulltoZeroCols +' FROM
(
SELECT RNO_ROWTOTAL,environment_name,root_cause,VALUE
FROM #NEWTABLE
) x
PIVOT
(
MIN(VALUE)
FOR [root_cause] IN (' + #cols + ')
) p
ORDER BY RNO_ROWTOTAL,environment_name;'
EXEC SP_EXECUTESQL #query
RESULT
I think you need to calculate the Total separately. Using this simple query for the total (sorry, had to give the alias name for your " " column):
select environment_name as en,
count (*) AS Total
FROM test1
WHERE value in ('Enviro', 'Requi', 'Dev', 'Tsc', 'TD', 'Unkn')
GROUP BY environment_name
you can easily join both queries together to get the required report:
SELECT * FROM
(select *
from
(
select environment_name as en, value
from test1
unpivot
(
value
for col in (root_cause)
) unp
) src
pivot
(
count(value)
for value in ([Enviro] , [Requi] , [Dev] , [Tsc], [TD] , [Unkn])
) piv
) AS a
INNER JOIN
( select environment_name as en,
count (*) AS Total
FROM test1
WHERE value in ('Enviro', 'Requi', 'Dev', 'Tsc', 'TD', 'Unkn')
GROUP BY environment_name
) AS b ON a.en = b.en
UNION ALL
SELECT * FROM
(select *
from
(
select 'Total' as en, value
from test1
unpivot
(
value
for col in (root_cause)
) unp
) src
pivot
(
count(value)
for value in ([Enviro] , [Requi] , [Dev] , [Tsc], [TD] , [Unkn])
) piv
) AS a
INNER JOIN
( select 'Total' as en,
count (*) AS Total
FROM test1
WHERE value in ('Enviro', 'Requi', 'Dev', 'Tsc', 'TD', 'Unkn')
) AS b
I have not tested it, but believe it will work
You can also put you select pivot, without totals, in a temp table and then add the totalS with a new select:
SELECT environment_name=ISNULL(environment_name, ‘Total’) , Enviro=SUM(Enviro), Requi=SUM(Requi), Dev=SUM(Dev), TSc=SUM(TSc), TD=SUM(TD), Unkn =SUM(Unkn),
Total = sum(Enviro+Requi+Dev+TSc+TD+Unkn)
FROM #temp
GROUP BY ROLLUP(environment_name)

SQL query for finding first missing sequence string (prefix+no)

T-SQL query for finding first missing sequence string (prefix+no)
Sequence can have a prefix + a continuing no.
ex sequence will be
ID
-------
AUTO_500
AUTO_501
AUTO_502
AUTO_504
AUTO_505
AUTO_506
AUTO_507
AUTO_508
So above the missing sequence is AUTO_503 or if there is no missing sequence then it must return next sequence.
Also starting no is to specified ex. 500 in this case and prefix can be null i.e. no prefix only numbers as sequence.
You could LEFT JOIN the id numbers on shifted(+1) values to find gaps in sequential order:
SELECT
MIN(a.offsetnum) AS first_missing_num
FROM
(
SELECT 500 AS offsetnum
UNION
SELECT CAST(REPLACE(id, 'AUTO_', '') AS INT) + 1
FROM tbl
) a
LEFT JOIN
(SELECT CAST(REPLACE(id, 'AUTO_', '') AS INT) AS idnum FROM tbl) b ON a.offsetnum = b.idnum
WHERE
a.offsetnum >= 500 AND b.idnum IS NULL
SQLFiddle Demo
Using a recursive CTE to dynamically generate the sequence between the min and max of the ID Numbers maybe over complicated things a bit but it seems to work -
LIVE ON FIDDLE
CREATE TABLE tbl (
id VARCHAR(55)
);
INSERT INTO tbl VALUES
('AUTO_500'),
('AUTO_501'),
('AUTO_502'),
('AUTO_504'),
('AUTO_505'),
('AUTO_506'),
('AUTO_507'),
('AUTO_508'),
('509');
;WITH
data_cte(id)AS
(SELECT [id] = CAST(REPLACE(id, 'AUTO_', '') AS INT) FROM tbl)
,maxmin_cte(minId, maxId)AS
(SELECT [minId] = min(id),[maxId] = max(id) FROM data_cte)
,recursive_cte(n) AS
(
SELECT [minId] n from maxmin_cte
UNION ALL
SELECT (1 + n) n FROM recursive_cte WHERE n < (SELECT [maxId] from maxmin_cte)
)
SELECT x.n
FROM
recursive_cte x
LEFT OUTER JOIN data_cte y ON
x.n = y.id
WHERE y.id IS NULL
Check this solution.Here you just need to add identity column.
CREATE TABLE tbl (
id VARCHAR(55),
idn int identity(0,1)
);
INSERT INTO tbl VALUES
('AUTO_500'),
('AUTO_501'),
('AUTO_502'),
('AUTO_504'),
('AUTO_505'),
('AUTO_506'),
('AUTO_507'),
('AUTO_508'),
('509');
SELECT min(idn+500) FROM tbl where 'AUTO_'+cast((idn+500) as varchar)<>id
try this:
with cte as(
select cast(REPLACE(id,'AUTO_','') as int)-500+1 [diff],ROW_NUMBER()
over(order by cast(REPLACE(id,'AUTO_','') as int)) [rnk] from tbl)
select top 1 'AUTO_'+cast(500+rnk as varchar(50)) [ID] from cte
where [diff]=[rnk]
order by rnk desc
SQL FIddle Demo
Had a similar situation, where we have R_Cds that were like this R01005
;with Active_R_CD (R_CD)
As
(
Select Distinct Cast(Replace(R_CD,'R', ' ') as Int)
from table
where stat = 1)
select Arc.R_CD + 1 as 'Gaps in R Code'
from Active_R_CD as Arc
left outer join Active_R_CD as r on ARC.R_CD + 1 = R.R_CD
where R.R_CD is null
order by 1