Multiple Selection in T-SQL and Transpose one cells to another's rows - sql

I have a project that has dynamic field details for an asp page. When the page is executed, the database is queried for the list of dynamic fields and then all the controls are created at runtime on the asp page. Now all these dynamic fields have corresponding data in another (or say more than one) tables.
The data in the Dynamic Control Detail table is like this:
FieldID | FieldName | MappingTableName | MappingColumnName
-------------------------------------------------------------------------
92 | txtPrsnFirstName | Table1 | FirstName
93 | txtPrsnLastName | Table1 | LastName
94 | ddlPrsnGender | Table2 | Gender
95 | txtCompany | Table2 | Company
96 | txtDesignation | Table1 | Designation
The corresponding datatable's data is as follows:
Table1:
PersonID | FirstName | LastName | Designation
-----------------------------------------
1 | Person1 | SomeName | Manager
2 | Person2 | MoreName | Executive
Table2:
PersonID | Gender | Company
--------------------------------------
1 | Male | ABC Cons
2 | Female | XYZ PVT.LTD
Now, currently what I have done is, created a stored proc, that returns all three tables data at once and I would fetch each one of them in a DataSet then I would iterate through the FieldTable data first and then fetch the corresponding data from Table1 and Table2
I need to write a query that fetches the data in a way that the data from Table1 and Table2 will get transposed in form of multiple rows (Fetches only one record at a time) something like this.
FieldID | FieldName | MappingTableName | MappingColumnName | Data
---------------------------------------------------------------------------------------
92 | txtPrsnFirstName | Table1 | FirstName | Person1
93 | txtPrsnLastName | Table1 | LastName | SomeName
94 | ddlPrsnGender | Table2 | Gender | Male
95 | txtCompany | Table2 | Company | ABC Cons
96 | txtDesignation | Table1 | Designation | Manager

I would add a hidden column (I will call it PersonMap) in the Field-Table which indicates a mapping between FieldID and PersonID (meaning: Field with ID XY shows data from Person Z).
Now create a function like (my TSQL is a little rusty - therefore pseudo-SQL):
create function returnPersonData(in tablename varchar, in columnname varchar, in personID varchar) RETURNS VARCHAR
BEGIN
declare res varchar;
set res = EXEC('SELECT %columnname% FROM %tablename% WHERE PersonID = %personID%');
return res;
END
Now use the created function for your Data_column. The FROM statement is your FieldTable + the PersonMap-column:
SELECT FieldID, FieldName, MappingTableName, MappingColumnName, (returnPersonData(MappingTableName, MappingColumnName, PersonMap) AS Data)
FROM (SELECT FieldID, FieldName, MappingTableName, MappingColumnName, (SELECT PersonID from somewhere) AS PersonMap FROM FieldTable ... )
I hope I covered you question... greetings.

Related

How to create a table from different query results SQL

I want to create a new table using the results from some queries. I might be looking at this the wrong way so please feel free to let me know. Because of this I will try to make this question simple without putting my code to match each employee number with each manager level column from table2
I have two tables, one has employee names and employee numbers example
table 1
+-------------+-----------+-------------+-------------+
| emplpyeenum | firstname | last name | location |
+-------------+-----------+-------------+-------------+
| 11 | joe | free | JE |
| 22 | jill | yoyo | XX |
| 33 | yoda | null | 9U |
+-------------+-----------+-------------+-------------+
and another table with employee numbers under each manager level so basically a hierarchy example
Table 2
+---------+----------+----------+
| manager | manager2 | manager3 |
+---------+----------+----------+
| 11 | 22 | 33 |
+---------+----------+----------+
I want to make a new table that will have the names besides the numbers, so for example but with employee number beside the names
+---------+--------+----------+
| level 1 | level2 | level3 |
+---------+--------+----------+
| jill | joe | yoda |
+---------+--------+----------+
How can I do this?
edit sorry guys I don't have permission to create a new table or view
Why not change your table2 to this?
+------------+----------+
| EmployeeId | ManagerId|
+------------+----------+
| 11 | NULL |
+------------+----------+
| 22 | 11 |
+------------+----------+
| 33 | 22 |
+------------+----------+
Then you can do what you want with the data. At least your data will be properly normalized. In your table2. What happen if employee 33 hire another employee below him? You will add another column?
Based on your available table, this should give you the result you want.
SELECT m1.firstname, m2.firstname, m3.firstname
FROM table2 t
LEFT JOIN table1 m1 ON m1.employeenum = t.manager
LEFT JOIN table1 m2 ON m2.employeenum = t.manager2
LEFT JOIN table1 m3 ON m3.employeenum = t.manager3
You can just do a basic create table, then do a insert select to that will fill the table the way you need it. All you have to do is replace the select statement that I provided with the one you used to create the levels table output.
create table Levels
(
level1 varchar(25),
level2 varchar(25),
level3 varchar(25)
)
insert into Levels(level1, level2, level3)
select * from tables --here you would put the select statement that you used to create the information. If you dont have this script then let me know

Pivot SSRS Dataset

I have a dataset which looks like so
ID | PName | Node | Val |
1 | Tag | Name | XBA |
2 | Tag | Desc | Dec1 |
3 | Tag | unit | Int |
6 | Tag | tids | 100 |
7 | Tag | post | AAA |
1 | Tag | Name | XBB |
2 | Tag | Desc | Des9 |
3 | Tag | unit | Float |
7 | Tag | post | BBB |
6 | Tag | tids | 150 |
I would like the result in my report to be
Name | Desc | Unit | Tids | Post |
XBA | Dec1 | int | 100 | AAA |
XBB | Des9 | Float | 150 | BBB |
I have tried using a SSRS Matrix with
Row: PName
Data: Node
Value: Val
The results were simply one row with Name and next row with desc and next with unit etc. Its not all in the same rows and also the second row was missing. This is possibly because there is no grouping on the dataset.
What is a good way of achieving the expected results?
I would not recommend this for a production scenario but if you need to knock out a report quickly or something you can try this. I would just not feel comfortable that the order of the records you get will always be what you expect.
You COULD try to insert the results of the SP into a table (regular table, temp table, table variable...doesn't matter really as long as you can get an identity column added). Assuming that the rows always come out in the correct order (which is probably not a valid assumption 100% of the time) then add an identity column on the table to get a unique row number for each row. From there you should be able to write some math logic to "group" your values together and then pivot out what you want.
create table #temp (ID int, PName varchar(100), Node varhar(100), Val varchar(100))
insert #temp exec (your stored proc)
alter table #temp add UniqueID int identity
then use UniqueID (modulo on 5 perhaps?) to group records together and then pivot

T-SQL split table and insert Id

I'm currently working on a stored procedure in T-SQL on SQL Server 2012. I need to merge 2 tables without an Id. The Id will be created on the insert into the first table. My problem is kind of tricky, thus maybe you can help me :)
In the stored procedure, the import table looks the following way:
CREATE TYPE [MySchema].[Target] AS TABLE
(
IsPrivate BIT,
IsPublic BIT,
CountryId VARCHAR(100)
);
GO
#TARGETS MySchema.Target READONLY
Some possible values for the import #Targets:
IsPrivate | IsPublic | CountryId |
----------+----------+-------------+
1 | 0 | CA,FR |
0 | 1 | US,GB |
Desired output: these #Targets I need to split up into 2 tables, Target and Country:
Create new entries in Target :
TargetId | IsPrivate | IsPublic |
---------+-----------+----------+
23 | 1 | 1 |
24 | 0 | 0 |
Split up the CountryId into it's own table, Country and add the TargetId:
Id | TargetId | CountryId |
---+----------+-----------+
1 | 23 | CA |
2 | 23 | FR |
3 | 24 | US |
4 | 24 | GB |
My current query looks like this:
CREATE TABLE #tmpTarget (TargetId INT, CountryId VARCHAR(100));
INSERT INTO [MySchema].[Target]([IsPrivate], [IsPublic])
OUTPUT inserted.TargetId, CountryId INTO #tmpTarget
SELECT IsPrivate, IsPublic
FROM #TARGETS
Of course this query doesn't work. I'm currently thinking of how to solve this issue. Do you have some ideas or useful tips for me on how to solve this problem?
Thanks a lot! :)

Dynamic view with dynamic list of columns in postgres

I have a scenario as follows:
Table User
ID User viewname Description
1 JamesId employeeview This is a employee
2 FredId employeeview This is a employee
3 NickId managerview This is a manager
Table properties
ID key value user_ref
1 name james 1
2 phone 88888888888 1
3 email test#test.com 3
4 name fred 2
5 phone 555555555555 2
I need to create views as following:
EmployeeView
Id empId name phone Description
1 JamesId james 88888888888 This is a employee
2 FredId fred 555555555555 This is a employee
ManagerView
Id empId email Description
1 NickId test#test.com This is a manager
properties table is a extension to User table where everything is stored as key value pair. Views need to be created dynamically using the above two tables. Properties table is dynamic.
Is it possible to generate such view. Can someone give a example to do it.
I managed to do it with crosstab function in postgres. However i had to modify the properties table to accommodate another colume as a identified.
Modified property table:
+------+-------+---------------+-------------+-------------------+
| **ID | key | value | user_ref | identifier** |
+------+-------+---------------+-------------+-------------------+
| 1 | name | james | 1 | viewemployee |
| 2 | phone | 88888888888 | 1 | viewemployee |
| 3 | email | test#test.com | 3 | viewmanager |
| 4 | name | fred | 2 | viewemployee |
| 5 | phone | 555555555555 | 2 | viewemployee |
+------+-------+---------------+-------------+-------------------+
Sql query using crosstab for employeeview:
create MATERIALIZED VIEW EmployeeView as
select one.id, one.userid, two.name, two.phone, one.description from
user_table one,
(SELECT *
FROM crosstab(
'SELECT user_ref,key,value FROM user_properties where identifier=''viewemployee'' order by 1,2')
AS
ct_row (user_ref int, name varchar, phone varchar)) two
where
one.id=two.user_ref
Sql query using crosstab for managerview:
create MATERIALIZED VIEW ManagerView as
select one.id, one.userid, two.email, one.description from
user_table one,
(SELECT *
FROM crosstab(
'SELECT user_ref,key,value FROM user_properties where identifier=''viewmanager'' order by 1,2')
AS
ct_row (user_ref int, email varchar)) two
where
one.id=two.user_ref

SQL: Join to different table based on column data

My scenario are as below:
Table: t_audit
row | colname | oldvalue | newvalue
===================================
1 | locid | 001 | 002
2 | typeid | 010 | 011
Table: t_ref_audit
colname | desc | link_table | link_key | link_desc
===========================================================
locid | Location | t_ref_loc | locid | loc_desc
typeid | Type | t_ref_type | typeid | type_desc
Table: t_ref_loc
locid | type_desc
==================
001 | LOCATION A
002 | LOCATION B
Table: t_ref_type
typeid | loc_desc
==================
010 | TYPE C
011 | TYPE D
As you can see from above, the first table is my audit log table, and 2nd table is the reference table. 3rd and 4th tables are reference tables. By using simple SQL below I can get the proper description for the column name based on t_ref_audit table.
SELECT t_ref_audit.desc, t_audit.oldvalue, t_audit.newvalue
FROM t_audit, t_ref_audit
WHERE t_audit.colname = t_ref_audit.colname
My problem now is, the columns on t_audit.oldvalue and t_audit.newvalue contains reference code ID from other reference tables (t_ref_loc & t_ref_type). I wanted to show the proper description based on columns from t_ref_audit.link_desc instead of just the ID as below:
coldesc | oldvalue | newvalue
==================================
Location | LOCATION A | LOCATION B
Type | TYPE C | TYPE D
Hope someone can enlighten me on this. Thank you.
Maybe something like this? (and the same logic for newvalues...)
SELECT
t_ref_audit.desc,
t_audit.oldvalue,
t_audit.newvalue,
case
when link_table='t_ref_loc' then t_ref_loc.loc_desc
when link_table='t_ref_type' then t_ref_type.type_desc
else '???'
end oldvalue_desc
FROM
t_audit
join t_ref_audit ON t_audit.colname = t_ref_audit.colname
left join t_ref_loc on link_table='t_ref_loc' and oldvalue=locid
left join t_ref_type on link_table='t_ref_type' and oldvalue=typeid
The logic works only for static mapping...
I think you mixed a bit t_ref_loc/t_ref_type tables and their titles.