问题
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#
??
回答1:
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.
回答2:
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)
回答3:
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?
来源:https://stackoverflow.com/questions/27543755/appending-data-in-t-sql