Column name determined by parameter - tsql

I've tried both approaches. First one has a syntax error. Second one shoves every column in the result instead of just the one that has a match with #LabelID.
SELECT (SELECT CASE #LabelID
WHEN 1 THEN count(h.ee_cmn_idfr) as 'DIR'
WHEN 2 THEN count(h.ee_cmn_idfr) as 'DD'
WHEN 3 THEN count(h.ee_cmn_idfr) as 'OD_Staff'
WHEN 4 THEN count(h.ee_cmn_idfr) as 'DI_BC'
WHEN 5 THEN count(h.ee_cmn_idfr) as 'DI_PLs'
WHEN 6 THEN count(h.ee_cmn_idfr) as 'DI_PQAs'
WHEN 7 THEN count(h.ee_cmn_idfr) as 'DI_FTEs'
WHEN 8 THEN count(h.ee_cmn_idfr) as 'AIPQBBC'
WHEN 9 THEN count(h.ee_cmn_idfr) as 'AIPQB_PL'
WHEN 10 THEN count(h.ee_cmn_idfr) as 'AIPQB_PQA'
WHEN 11 THEN count(h.ee_cmn_idfr) as 'AIPQB_GS13S'
WHEN 12 THEN count(h.ee_cmn_idfr) as 'AIPQB_FTE'
WHEN 13 THEN count(h.ee_cmn_idfr) as 'IT_Staff'
WHEN 14 THEN count(h.ee_cmn_idfr) as 'IT_Sup'
)
second approach:
SELECT
CASE WHEN #LabelID = 1 THEN count(h.ee_cmn_idfr) as 'DIR'
,CASE WHEN #LabelID = 2 THEN count(h.ee_cmn_idfr) END as 'DD'
,CASE WHEN #LabelID = 3 THEN count(h.ee_cmn_idfr) END as 'OD_Staff'
,CASE WHEN #LabelID = 4 THEN count(h.ee_cmn_idfr) END as 'DI_BC'
,CASE WHEN #LabelID = 5 THEN count(h.ee_cmn_idfr) END as 'DI_PLs'
,CASE WHEN #LabelID = 6 THEN count(h.ee_cmn_idfr) END as 'DI_PQAs'
,CASE WHEN #LabelID = 7 THEN count(h.ee_cmn_idfr) END as 'DI_FTEs'
,CASE WHEN #LabelID = 8 THEN count(h.ee_cmn_idfr) END as 'AIPQBBC'
,CASE WHEN #LabelID = 9 THEN count(h.ee_cmn_idfr) END as 'AIPQB_PL'
,CASE WHEN #LabelID = 10 THEN count(h.ee_cmn_idfr) END as 'AIPQB_PQA'
,CASE WHEN #LabelID = 11 THEN count(h.ee_cmn_idfr) END as 'AIPQB_GS13S'
,CASE WHEN #LabelID = 12 THEN count(h.ee_cmn_idfr) END as 'AIPQB_FTE'
,CASE WHEN #LabelID = 13 THEN count(h.ee_cmn_idfr) END as 'IT_Staff'
,CASE WHEN #LabelID = 14 THEN count(h.ee_cmn_idfr) END as 'IT_Sup'

Here is how you would do it using dynamic SQL:
SAMPLE DATA:
IF OBJECT_ID('tempdb..#INPUT') IS NOT NULL
DROP TABLE #INPUT;
CREATE TABLE #INPUT(RowID INT IDENTITY(1, 1)
, ee_cmn_idfr INT);
INSERT INTO #INPUT(ee_cmn_idfr)
VALUES
(1),
(1),
(1),
(1),
(1),
(1),
(1),
(1),
(1),
(1),
(1),
(1);
SQL QUERY:
DECLARE #LabelID INT = 1; --<-- set the labelID
DECLARE #SQL NVARCHAR(MAX) = ''; --<-- declare a variable to hold the dynamic sql
SELECT #SQL = 'SELECT COUNT(ee_cmn_idfr) AS '+QUOTENAME(CASE #LabelID
WHEN 1 THEN 'DIR'
WHEN 2 THEN 'DD'
WHEN 3 THEN 'OD_Staff'
WHEN 4 THEN 'DI_BC'
WHEN 5 THEN 'DI_PLs'
WHEN 6 THEN 'DI_PQAs'
WHEN 7 THEN 'DI_FTEs'
WHEN 8 THEN 'AIPQBBC'
WHEN 9 THEN 'AIPQB_PL'
WHEN 10 THEN 'AIPQB_PQA'
WHEN 11 THEN 'AIPQB_GS13S'
WHEN 12 THEN 'AIPQB_FTE'
WHEN 13 THEN 'IT_Staff'
WHEN 14 THEN 'IT_Sup'
END)+' FROM #INPUT'; --<-- you'll have to change the name of the table accordingly
PRINT(#SQL); --<-- print out the query not needed but nice to have for debuging
EXEC (#SQL); --<-- execute the dynamic sql
the PRINT(#SQL) will print the following:
SELECT COUNT(ee_cmn_idfr) AS [DIR] FROM #INPUT
RESULTS:
the above code will select the column name as follows:
WHEN 1 THEN 'DIR'
WHEN 2 THEN 'DD'
WHEN 3 THEN 'OD_Staff'
WHEN 4 THEN 'DI_BC'
WHEN 5 THEN 'DI_PLs'
WHEN 6 THEN 'DI_PQAs'
WHEN 7 THEN 'DI_FTEs'
WHEN 8 THEN 'AIPQBBC'
WHEN 9 THEN 'AIPQB_PL'
WHEN 10 THEN 'AIPQB_PQA'
WHEN 11 THEN 'AIPQB_GS13S'
WHEN 12 THEN 'AIPQB_FTE'
WHEN 13 THEN 'IT_Staff'
WHEN 14 THEN 'IT_Sup'

Related

Columns to Rows in T-SQL

I have table tbl_Survey:
SurveyID 1 2 3 4
7 4 4 4 4
8 3 3 3 3
9 2 2 2 2
My goal is to transfer table headers - 1 2 3 4 into rows, as the following:
enter
SurveyID Ouestion Rating
7 1 4
7 2 4
7 3 4
7 4 4
8 1 3
8 2 3
8 3 3
8 4 3
9 1 2
9 2 2
9 3 2
9 4 2
My code is (trying to follow help recommendations):
SELECT [SurveyID]
,[Question]
,[Rating]
FROM
[tbl_Survey]
cross apply
(
values
('1', 1 ),
('2', 2 ),
('3', 3 ),
('4', 4 )
) c (Question, Rating);
Results are not fully correct (Rating column is a problem):
SurveyID Ouestion Rating
7 1 1
7 2 2
7 3 3
7 4 4
8 1 1
8 2 2
8 3 3
8 4 4
9 1 1
9 2 2
9 3 3
9 4 4
Please, help...
My problem (because of which I couldn't proceed) was that I haven't used brackets for my code.
Here is the updated code for this:
SELECT [SurveyID], [Question], [Rating]
FROM [dbo].[tbl_Survey]
UNPIVOT
(
[Rating]
FOR [Question] in ([1], [2], [3], [4])
) AS SurveyUnpivot
How about this:
DECLARE #T TABLE (SurveyID int, q1 int, q2 int, q3 int, q4 int)
INSERT #T (SurveyID, q1, q2, q3, q4)
VALUES (7,4,4,4,4), (8,3,3,3,3), (9, 2, 2, 2, 2)
SELECT SurveyID, REPLACE(Question,'q','') as Question, Rating
FROM #T UNPIVOT (Rating FOR Question in (q1, q2, q3, q4)) as UPV
Same approach. Just make sure you use a global temporary table as a temp table will not be visible in the scope of the EXEC statement. This should work with any column name and any number of columns.
IF OBJECT_ID('tempdb..##T') IS NOT NULL DROP TABLE ##T
CREATE TABLE ##T (SurveyID int, xxxxx int, yyyyy int, zzzzzz int, tttttt int)
INSERT ##T VALUES (7,4,4,4,4), (8,3,3,3,3), (9, 2, 2, 2, 2)
DECLARE #Colnames nvarchar(4000)
SELECT #Colnames = STUFF((SELECT ',[' + [name] +']' FROM tempdb.sys.columns where object_id = object_id('tempdb..##T') AND name <> 'SurveyID' FOR XML PATH('') ),1,1,'')
DECLARE #SQL nvarchar(4000) SET #SQL = 'SELECT SurveyID, Question, Rating FROM ##T UNPIVOT (Rating FOR Question in ('+#colnames+')) as UPV'
EXEC(#SQL)

Change value of variable in pl/sql

I am running a unix *_sh script but with methods that use pl/sql in it.
Method in the script:
method(){
sqlplus -s ${DB_CONNECTION} << EOF
set echo on;
set timing on;
set serveroutput on;
DECLARE
v_monthNow Date:=to_date('2018-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS');
v_charMonthNow Varchar(5):=to_char(v_monthNow,'MM');
v_charMonthBefore Varchar(5) :=to_char(v_monthNow, 'MM')-1;
BEGIN
dbms_output.Put_line('SYSDATE is '|| v_monthNow ||' || MonthNow is '|| v_charMonthNow);
IF v_charMonthBefore = '0'
set v_charMonthBefore = '12'
dbms_output.Put_line('MonthBefore is '|| v_charMonthBefore);
ELSE
dbms_output.Put_line('MonthBefore is '|| v_charMonthBefore);
END;
/
EOF
}
My question is: how do I set value of v_charMonthBefore to what I want?
Actually if sysdate is Jan 2018, i need v_monthNow=1 and v_charMonthBefore=12
if sysdate is Feb 2018, i need v_monthNow=2 and v_charMonthBefore=1
Other way to do this is not required, i just need to fix what i have now as i am not really familiar with pl/sql.
Thank you
Use CASE to detect the correct value.
My CTE is here just to create all 12 months in a year. You need lines 7 - 10.
SQL> with test as
2 (select to_number(to_char(add_months(trunc(sysdate, 'yyyy'), level - 1), 'mm')) mon
3 from dual
4 connect by level <= 12
5 )
6 select
7 mon as v_month_now,
8 case when mon = 1 then 12
9 else mon - 1
10 end as v_month_before
11 from test;
V_MONTH_NOW V_MONTH_BEFORE
----------- --------------
1 12
2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8
10 9
11 10
12 11
12 rows selected.
SQL>

TSQL - First and last number in range

I have table with:
1
2
3
4
5
6
9
10
11
12
and I need to receive:
1-6
9-12
How I can do that?
I need to see that I have two or more range of number i table and that from 1 to 6 and from 9 to 12.
SELECT
CONCAT(MIN(A.b), '-', max(A.b))
FROM
(
SELECT
*,
ROW_NUMBER() OVER (ORDER BY b) RowId
FROM
(VALUES (1), (2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) a(b)
--WHERE
--(a.b >= 1 AND a.b <= 6) OR
--(a.b >= 9 AND a.b <= 12)
) A
GROUP BY
A.b - A.RowId

TSQL recursive CTE order

I am having trouble figuring out how I can use recursive CTEs to order my results recursively. Here is what I mean (this is a simplified dataset):
I have this as input:
declare #sections table (id int, parent int);
insert into #sections values (1, 1);
insert into #sections values (2, 2);
insert into #sections values (3, 2);
insert into #sections values (4, 2);
insert into #sections values (5, 4);
insert into #sections values (6, 1);
insert into #sections values (7, 6);
insert into #sections values (8, 6);
insert into #sections values (9, 6);
insert into #sections values (10, 9);
-- hierarchical view
--1
-- 6
-- 7
-- 8
-- 10
-- 9
--2
-- 3
-- 4
-- 5
And I want this as output
EDIT: The order of the rows is the important part here
-- id parent depth
-- 1 1 0
-- 6 1 1
-- 7 6 2
-- 8 6 2
-- 10 8 3
-- 9 6 2
-- 2 2 0
This is the best I can do:
with section_cte as
(
select id, parent, 0 'depth' from #sections where id = parent
union all
select cte.id, cte.parent, depth + 1
from #sections s join section_cte cte on s.parent = cte.id where s.id <> s.parent
)
select *from section_cte
Can anyone please help me tweak this query to get what I need?
Thanks!
You missed the part where you need to identify the depth is from the cte
WITH CTE AS (
SELECT
id
, parent
, 0 AS depth
FROM
#sections
WHERE
id=parent
UNION ALL
SELECT
s.id
, s.parent
, c.depth + 1
FROM
#sections s
JOIN CTE c ON s.parent=c.id AND s.id <> s.parent
)
SELECT *
FROM CTE;
During the recursive build, it is a small matter to add a sequence. In the example below, the order is driven by the alphabetical order of the title, but you can use any other available key/sequence.
Declare #Table table (ID int,Pt int,Title varchar(50))
Insert into #Table values (0,null,'Tags'),(1,0,'Transportation'),(2,1,'Boats'),(3,1,'Cars'),(4,1,'Planes'),(5,1,'Trains'),(6,0,'Technology'),(7,6,'FTP'),(8,6,'HTTP'),(9,0,'Finance'),(10,9,'FTP'),(11,9,'401K'),(12,2,'Sail'),(13,2,'Powered'),(14,6,'Internet'),(15,6,'Database'),(16,15,'SQL Server'),(17,15,'MySQL'),(18,15,'MS Access')
Declare #Top int = null --<< Sets top of Hier Try 9
Declare #Nest varchar(25) =' ' --<< Optional: Added for readability
;with cteHB (Seq,ID,Pt,Lvl,Title) as (
Select Seq = cast(1000+Row_Number() over (Order by Title) as varchar(500))
,ID
,Pt
,Lvl=1
,Title
From #Table
Where IsNull(#Top,-1) = case when #Top is null then isnull(Pt,-1) else ID end
Union All
Select Seq = cast(concat(cteHB.Seq,'.',1000+Row_Number() over (Order by cteCD.Title)) as varchar(500))
,cteCD.ID
,cteCD.Pt,cteHB.Lvl+1
,cteCD.Title
From #Table cteCD
Join cteHB on cteCD.Pt = cteHB.ID)
,cteR1 as (Select Seq,ID,R1=Row_Number() over (Order By Seq) From cteHB)
,cteR2 as (Select A.Seq,A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID )
Select Hier='HierName'
,B.R1
,C.R2
,A.ID
,A.Pt
,A.Lvl
,Title = Replicate(#Nest,A.Lvl) + A.Title
--,A.Seq --<< Normally Excluded, but you can see how the sequence is built
From cteHB A
Join cteR1 B on A.ID=B.ID
Join cteR2 C on A.ID=C.ID
Order By A.Seq --<< Use R1 if Range Keys are used
Returns
Hier R1 R2 ID Pt Lvl Title
HierName 1 19 0 NULL 1 Tags
HierName 2 4 9 0 2 Finance
HierName 3 3 11 9 3 401K
HierName 4 4 10 9 3 FTP
HierName 5 12 6 0 2 Technology
HierName 6 9 15 6 3 Database
HierName 7 7 18 15 4 MS Access
HierName 8 8 17 15 4 MySQL
HierName 9 9 16 15 4 SQL Server
HierName 10 10 7 6 3 FTP
HierName 11 11 8 6 3 HTTP
HierName 12 12 14 6 3 Internet
HierName 13 19 1 0 2 Transportation
HierName 14 16 2 1 3 Boats
HierName 15 15 13 2 4 Powered
HierName 16 16 12 2 4 Sail
HierName 17 17 3 1 3 Cars
HierName 18 18 4 1 3 Planes
HierName 19 19 5 1 3 Trains
Now, you may have noticed R1 and R2. These are my range keys, and are often used to aggregate data without recursion. If you don't need or want these, just remove the cteR1 and cteR2 (and the corresponding references in the final SELECT).
EDIT
You also have the option of selecting a portion of the hierarchy (i.e. Technology and its children).
The trick you need is to create a sortstring which match your business rule. Something like this.
WITH CTE AS (
SELECT
id, parent, 0 AS depth
--For MS SQL Server 2012+
,cast(format(id,'0000') as varchar(max)) sort
--For previous versions
,cast(stuff('0000',5-len(cast(id as varchar)),len(cast(id as varchar)),id) as varchar(max)) sort1
FROM #sections
WHERE id=parent
UNION ALL
SELECT s.id, s.parent, c.depth + 1
,sort + cast(format(s.id,'0000') as varchar(max)) sort
,sort + cast(stuff('0000',5-len(cast(s.id as varchar)),len(cast(s.id as varchar)),s.id) as varchar(max)) sort1
FROM #sections s
inner join CTE c ON s.parent=c.id AND s.id <> s.parent
)
SELECT *
FROM CTE
order by sort --or by sort1 depending on version

Group by in pivot table in SQL Server 2008 R2

How can I group by this pivot table
select *
from
(SELECT
ProductionID,ProductionDetailID,
[DeviceID],[DeviceSpeed],[LattNO]
from
(SELECT
*
from view_3
where ProductionID = 6) x pivot
(
max(Value)FOR PropertyName in ([DeviceID],[DeviceSpeed],[LattNO])
) AS pvt ) as pp
Result:
ProductionID ProductionDetailID DeviceID DeviceSpeed LattNO
6 2 5 NULL NULL
6 2 NULL 8 NULL
6 2 NULL NULL 6
6 3 1 NULL NULL
6 3 NULL 2 NULL
and how can I get this result:
ProductionID ProductionDetailID DeviceID DeviceSpeed LattNO
6 2 5 8 6
6 3 1 2 NULL
SELECT
ProductionID,ProductionDetailID, Sum(Cast(isnull([DeviceID],0) as Int)) [DeviceID],Sum(Cast(isnull([DeviceSpeed],0) as Int)) [DeviceSpeed],Case Sum(Cast(isnull([LattNO],0) as Int)) When 0 then Null else Sum(Cast(isnull([LattNO],0) as Int)) End [LattNO] from
(
SELECT
* FROM dbo.View_3
)
x pivot
(
max(Value)FOR PropertyName in ([DeviceID],[DeviceSpeed],[LattNO])
) AS pvt
Group by ProductionID , ProductionDetailID