How to Join single table to it self in SQL Server 2008? - c#

I am using below table structure, I want to create a view which will show a FirstName of ReportsTo field shown below.
Please let me give a suggestion how to create that view which will display all the reports to 's first name with (',') comma separator.

You join a table to itself just like any other join. The main this is to make sure both tables are aliased with differnt aliases
Your problem is that you have a one to many relationship stored in the table which is a huge design mistake. For the future, remember that anytime you think about storing information a comma delimted list, then you are doing it wrong and need a related table instead. So first you have to split the data out into the related table you should have had instead with two columns, EmplCode and ReportsTo (with only one value in reports to), then you can do the join just like any other join. We use a function that you can get by searching around the internet called fn_split to split out such tables when we get this type of infomation in client files.
If you search out fn_split, then this is how you can apply it:
Create table #UnsplitData (EmpCode varchar (10), ReportsTo varchar(20), FirstName varchar (10))
insert into #UnsplitData
values ('emp_0101', 'emp_0102,emp_0103', 'John')
, ('emp_0102', 'emp_0103', 'Sally')
, ('emp_0103', Null, 'Steve')
select *, employee.FirstName + ', ' + Reports.FirstName
from #UnsplitData Employee
join
(
select t.EmpCode , split.value as Reportsto, ReportName.Firstname
from #UnsplitData t
cross apply dbo.fn_Split( ReportsTo, ',') split
join #UnsplitData ReportName
on ReportName.EmpCode = split.value
) Reports
On Employee.EmpCode = Reports.empcode

From what I gather, I think you're trying to get the Firstname column and the ReportsTo column separated by a comma:
SELECT FirstName + ', ' + ReportsTo
FROM table
Edit: judging from the comments he's trying to do something else? Can someone rephrase for me?

SELECT E.*,
R.FirstName
FROM Employees E
JOIN Employees R
ON E.ReportsTo LIKE '%' + R.EmpCode + '%'

Related

Breakdown / Documentation of a SQL Query

I have a very large, complex, and undocumented database. I have a task to provide a document which would show which tables and columns have been used for all stored procedures, functions, etc.
According to my research majority of queries will have the similar format to this:
SELECT u.FirstName , u.LastName, a.AccountNumber
FROM Username u
LEFT JOIN Account a
ON a.UserID = u.UserID
~90% of tables and columns will have aliases.
Further, I do have a table with 2 columns - function/sproc name, and its SQL code.
I am looking for a method (preferably SQL, but can be C#) which would output the following results for the above SQL code:
Username - FirstName
Username - LastName
Username - UserID
Account - UserID
Account - AccountNumber
What would be the best approach to achieve this? I have tried to join each SQL code cell with INFORMATION_SCHEMA.COLUMNS but I get inaccurate results, say when column name appears in the COLUMNS table, but was not actually used for that specific table in the SQL code cell.
Thanks
Probably you want to look at the dependencies on the stored procedure/function that you are looking at?
Take a look at https://www.mssqltips.com/sqlservertip/1768/identifying-object-dependencies-in-sql-server/
e.g. if the procedure name is dbo.myproc, something like the below
SELECT '* ' + referenced_entity_name + ' - ' + referenced_minor_name
FROM sys.dm_sql_referenced_entities ('dbo.myproc', 'OBJECT')
WHERE referenced_minor_name is not null;

Appending data in T-SQL

I have a sql (transact sql - SQL server 2012) which used to fetch names of customers from a table (Customer) who has valid addresses (from table Details):
Select Customer.Name, Details.Address
from Customer
left outer join Details on Details.Customer = Customer.Name
This used to send back each record (name) row for each customer every time from the db server. No multiple records are fetched.
Recently I needed to modify this sql text in order to fetch even the name of the books they have borrowed as per the database, which is saved in another table (Lending). Now the script looks like:
Select Customer.Name, Details.Address, Lending.BookName
from Customer
left outer join Details on Details.Customer = Customer.Name
left outer join Lending on Lending.CustomerName = Customer.Name
It is returning the records properly, but now I have got a problem. Since a customer can borrow multiple books, the returned data has multiple rows for the same customer showing multiple book names. According to my software specification I need to fetch one line for each customer and in that one row i need to append all the book names in a single column.
Can someone help me with this: How to append multiple data for same record in a single column such as:
Name Address BookName
Somdip XX Brief History of Time,Headfirst SQL,Headfirst C#
instead of
Name Address BookName
Somdip XX Brief History of Time
Somdip XX Headfirst SQL
Somdip XX Headfirst C#
??
I used the above sql text with 'where' and 'order by' clauses such as :
SELECT Name,
Address ,
Split.a.value('.', 'VARCHAR(100)') BookName
FROM (SELECT Name,
Address ,
Cast ('<M>' + Replace(BookName, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM [table] where ID = '1' order by Name) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
and it is giving me an error: The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
try this:
SELECT Name,
Address ,
Split.a.value('.', 'VARCHAR(100)') BookName
FROM (SELECT Name,
Address ,
Cast ('<M>' + Replace(BookName, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM [table]) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
While I think this is generally a bad idea - returning multiple data items in a single cell - there are a number of ways to go about it, with different performance concerns.
What you're looking for is here: Concatenate many rows into a single text string?

Displaying many to many data in SQL Server in visual studio using c#

I know this is possible but I can't think of a way to display this.
Assume that a doctor can have many specialization.
DOCTOR :- DOC_ID, DOC_NAME, SPEC_ID
then a table that is a foreign key to the former, namely
SPECIALIZATION :- SPEC_ID, SPEC_NAME
Then the linking table "I forgot what is the technical term for this" that is a foreign key respectively, namely
DOCTORSPECIALIZATION :- DOC_ID, SPEC_ID
How to display this in visual studio?
There are two way to do this, first In SQL and second is C# code.
In SQL:-
DECLARE #DOC_ID = 1234
1. Fetch Doctor SPEC Name and Take into Temp table
CREATE TABLE #tempDOC_SPEC
(
SPEC_ID int,
SPEC_NAME varchar(100)
)
INSERT INTO #tempDOC_SPEC
SELECT SPECIALIZATION.SPEC_ID, SPECIALIZATION.SPEC_NAME
FROM DOCTORSPECIALIZATION a INNER JOIN SPECIALIZATION b ON a.SPEC_ID = b.SPEC_ID
WHERE DOC_ID = #DOC_ID
2. Stuff data from this temp table to get desired results
SELECT DOC_ID, DOC_NAME,
STUFF((Select ', '+ #tempDOC_SPEC.SPEC_NAME FROM tempDOC_SPEC FOR XML PATH('')), 1, 1, '')
AS SPEC_Name
FROM DOCTOR
WHERE DOC_ID = #DOC_ID
This SQL query give the Doc name, Spec_Name as comma separated value in single column.
In C#:-
we have to loop through for each Doctor name and display the Spec_Name.

Reversing cross join input

A table is populated by the following stored procedure:
exec('
insert into tblSegments
(SegmentName, CarTypeID, EngineTypeID, AxleTypeID)
select distinct
''' + #SegmentName + '''
, CT.CarTypeID
, ET.EngineTypeID
, AT.AxleTypeID
from
tblCarTypes CT
cross join tblEngineTypes ET
cross join tblAxleTypes AT
where
CT.CarTypeName in (' + #CarTypes + ')
and ET.EngineTypeName in (' + #EngineTypes + ')
and AT.AxleTypeName in (' + #AxleTypes + ')
')
parameters, with the exception of #SegmentName, are strings such as (for #CarTypes) 'hatchback','suv','sedan'.
Can the data in the table be used to create a list, for a single SegmentName, of the previous entries to the stored procedure akin to
Run1: #CarTypes, #EngineTypes, #AxleTypes
Run2: #CarTypes, #EngineTypes, #AxleTypes
Run3: #CarTypes, #EngineTypes, #AxleTypes
...?
Runs don't need to be in sequential order. The process can involve a combination of T-SQL and C#. I'm pretty sure this is impossible; perhaps someone can prove me wrong.
No, it's not possible because you're taking in a potentially comma-delimited string of values which will create separate rows in your result table. You can easily get a single value each for the CarTypes, EngineTypes and AxleTypes variables, but to group them separately by each execution of your dynamic SQL you would need some kind of executionID column or something to group the rows on per execution.
So you're correct in that what you want to do is completely possible, but not with the schema design you've provided. I would just create another table and populate it at runtime if this is information you want to keep. You could put an identify column on the table that houses the input variables and use the ##IDENTITY for the insert into that table to populate an executionID column in your main table so you can easily associate the variable summary table with the cross joined result table.

Using C# to Select from SQL database Table

I have a List of UserID's and a open connection to SQL Server. How can I loop through this List and Select matching UserID with First_Name and Last_Name columns? I assume the output can be in a datatable?
many thanks
It varies slightly depending on which type of SQL you're running, but this and this should get you started.
The most expedient way of doing this would be to:
Turn the List into a string containing a comma separated list of the userid values
Supply that CSV string into an IN clause, like:
SELECT u.first_name,
u.last_name
FROM USER_TABLE u
WHERE u.userid IN ([comma separated list of userids])
Otherwise, you could insert the values into a temp table and join to the users table:
SELECT u.first_name,
u.last_name
FROM USER_TABLE u
JOIN #userlist ul ON ul.userid = u.userid
Write a function in your SQL database named ParseIntegerArray. This should convert a comma delimited string into a table of IDs, you can then join to this in your query. This also helps to avoid any SQL injection risk you could get from concatenating strings to build SQL. You can also use this function when working with LINQ to SQL or LINQ to Entities.
DECLARE #itemIds nvarchar(max)
SET itemIds = '1,2,3'
SELECT
i.*
FROM
dbo.Item AS i
INNER JOIN dbo.ParseIntegerArray(#itemIds) AS id ON i.ItemId = id.Id
This article should help you: http://msdn.microsoft.com/en-us/library/aa496058%28SQL.80%29.aspx
I've used this in the past to create a stored procedure accepting a single comma delimited varchar parameter.
My source from the C# program was a checked list box, and I built the comma delimited string using a foreach loop and a StringBuilder to do the concatenation. There might be better methods, depending on the number of items you have in your list though.
To come back to the SQL part, the fn_Split function discussed in the article, enables you to transform the comma delimited string back to a table variable that SQL Server can understand... and which you can query in your stored procedure.
Here is an example:
CREATE PROCEDURE GetSelectedItems
(
#SelectedItemsID Varchar(MAX) -- comma-separated string containing the items to select
)
AS
SELECT * FROM Items
WHERE ItemID IN (SELECT Value FROM dbo.fn_Split(#SelectedItemsIDs,','))
RETURN
GO
Note that you could also use an inner join, instead of the IN() if you prefer.
If you don't have the fn_Split UDF on your SQL Server, you can find it here: http://odetocode.com/Articles/365.aspx
I hope this helps.

Categories

Resources