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?
Related
I am trying to create a query to help get a list of accounts from an existing database. I will have two lists of integers passed in through two Table Value Parameters(TVP) from C#. I then need to see if multiple columns have any of the values in the corresponding TVP tables. The TVP lists of integers are provided by different clients and may differ between clients. That is why they are TVP's to allow the values to be passed in as parameters.
The data structure cannot be changed, it is created based on data from another system. Comments about changing the data structure won't be helpful. To help I will talk about an example table that would help show what I need.
Looking at a table like the following:
Table Accounts
varchar(200) AccountId
int StatusId1
int StatusId2
int StatusId3
int StatusId4
int Identifier1
int Identifier2
int Identifier3
int Identifier4
int Identifier5
I know that I can do a sql statement like:
Select AccountId from Accounts where StatusId1 In (1,2,3)
I was able to learn that I can reverse the In command as well:
Select AccountId from Accounts where 1 In (StatusId1, StatusId2, StatusId3, StatusId4)
This only lets me check one value against each column. The problem is I need to mix the two while using the TVP for the list of integers.
The closest I have been able to create is the following:
--Load the TVP lists
SELECT * INTO #StatusCodes FROM #StatusId
SELECT * INTO #IdentityCodes FROM #IdentifierId
--Find the Accounts that have the chosen Ids
SELECT AccountId
FROM Accounts
WHERE StatusId1 IN( SELECT Id FROM #StatusCodes)
OR StatusId2 IN( SELECT Id FROM #StatusCodes)
OR StatusId3 IN( SELECT Id FROM #StatusCodes)
OR StatusId4 IN( SELECT Id FROM #StatusCodes)
OR Identifier1 IN (SELECT Id FROM #IdentityCodes)
OR Identifier2 IN (SELECT Id FROM #IdentityCodes)
OR Identifier3 IN (SELECT Id FROM #IdentityCodes)
OR Identifier4 IN (SELECT Id FROM #IdentityCodes)
OR Identifier5 IN (SELECT Id FROM #IdentityCodes)
This query worked in my prototype and I got back the list of accounts that had at least one of these ids. I see a lot of select statements and it doesn't look very good. I am not sure how well it performs either. I am wondering if there is a better way to do this?
This is for a system that creates a report based on conditions our clients make. Each client runs from a couple to 100 reports each night. That means this is run possibly hundreds of times each night. While it isn't a system running thousands of times per hour, it does process a lot of data. Some of the databases it will search will be big with lots of accounts to search.
One option uses exists:
select a.acountId
from accounts a
where
exists (
select 1
from #StatusCodes s
where s.id in (a.StatusId1, a.StatusId2, a.StatusId3, a.StatusId4)
)
or exists (
select 1
from #IdentityCodes i
where i.id in (a.Identifier1, a.Identifier2, a.Identifier3, a.Identifier4)
)
I wanted to know that what may be the best practice to search for keywords or sentence in SQL Server.
Suppose I have a table say products with name, description and keywords. I have a search function in my website where the user may type in anything (sentence or single word).
I query the product table columns using like clause and shortlist the list to rows containing the search criteria.
To reduce the response time in case if the volume of data in product table is large, I add a pagination query of 10.
My current query
select *
from
(select
srno as productid, name +' '+ descriptions +' '+ keywords as search
from
ProductDetails) PD
where
PD.search LIKE '%bed%'
OR PD.search LIKE '%sheets%'
Here I have combined the three columns namely name,descriptions and keywords and I am searching for "bed sheets" in my product table
Is the above explained scenario a good practice?
Table Structure
ProductDetails example
srno|Name|Description|keywords
1|Floral Bed Sheets|..some text..|bed sheets
2|Square Pillow Covers|.. some text..|pillow covers square
Is it proper to place keywords in a separate column or should I create a new table for keywords.
If I have to create a new table for keywords, how to modify the above query?
Thanks in advance
I have 3 tables (for example 3, but in real over than 30 tables with this conditions) in my SQL Server database: post, user, person.
post: (post_id, post_text, user_id)
user: (user_id, user_name, person_id)
person: (person_id, person_phone, person_email)
Now, in C#, I want an algorithm that creates a query that get result like this:
post.post_id, post.post_text, post.user_id, user.user_id, user.user_name, user.person_id, person.person_id, person.person_email
and I use this method for fill a SqlDataReader in C# for reading and accessing all column values from these records.
I know that the common way to get that result directly and manually using of 'Join' statement, but it is waste time if tables count is very much. So, I want an algorithm that generates this query for manipulate in C# programming.
Thanks a lot.
To query all column names from your tables, you can use:
SELECT obj.Name + '.' + col.Name AS name
FROM sys.columns col
INNER JOIN sys.objects obj
ON obj.object_id = col.object_id
WHERE obj.Name IN ('post', 'user', 'person')
ORDER BY name
Then, for how to call this from C# using SqlDataReader, you can use this documentation: https://msdn.microsoft.com/en-us/library/haa3afyz(v=vs.110).aspx
select post1.post_id, post1.post_text, post1.user_id, user1.user_id, user1.user_name, user1.person_id, person1.person_id, person1.person_email from post post1 inner join user user1 on user1.user_id=post1.user_id inner join person person1 on person1.person_id=user1.person_id
I am issuing an SQL query in my visual studio application to search a database. I am having trouble joining two tables into one query search. I am looking to combine the First and Last name of an employee and match it up to a phone number. In one table I have an abbreviated name, and on the other table I have the full name.
Example
Code
cmdTxt.Append("SELECT partner.staffid, staff.Forename,staff.surname FROM tblpartner LEFT JOIN tblstaff ON staff.StaffID = partner.staffid ORDER BY staff.forename , staff.surname ");
I would Like to have a field that shows the Forename , surename, and phone number in one query search
You are using "partner" and "staff" as table aliases, but you aren't assigning those aliases to the table names. If you want to use those instead of the full table names, you need:
SELECT partner.staffid, staff.Forename,staff.surname, partner.phone
FROM tblpartner partner
LEFT JOIN tblstaff staff ON staff.StaffID = partner.staffid
ORDER BY staff.forename , staff.surname
As general advice, get your query working outside of your string literal; enter it into SQL Server Management Studio or something similar. Had you done that, it should have clearly showed you what the problem was. Then when you have your query set how you want, you can copy it into your Command Text in your Visual Studio application.
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 + '%'