Combine Multiple Rows Into A Single Column - sql

I am working on a stored procedure for reporting purposes and I need to combine rows in a single column but I can't find a way to do this. I have four tables, Case, Debtor, DebtorAddress and CaseNote. Rather than try to do this in a single statement I decided to create a temp table with the columns needed, populate the ones that occupy a single row, then use an update statement to combine the multiple rows of the last column needed into a single row. My temp table has rows for CApKey (the ID of the Case table), OwnerName (from Debtor), Address (from DebtorAddress, and Note. For each Case there may be multiple Notes (stored in the CaseNote table). So I may have Case #1, with a CApKey value of 1, OwerName of John Jones, Address of 1234 Main St. There may be one Note the says 'Called and left message', another that says 'Sent letter', and another that says 'Left a second voicemail', etc. I'd like to combine the three notes into a single row with Note values of Called and left a message, Sent Letter, and Left a second voicemail. I can use space, period, or comma as a delimiter. I found a way to do the update in theory but I'm getting an error that the sub-query returned more than 1 value. Below is the "heart" of the procedure. I've been wracking my brain on this for two days now. Any assistance is greatly appreciated in advance. Here is the statement I'm trying:
CREATE TABLE #temp
(
CaseKey int,
OwnerName varchar(500),
Address varchar(500),
Note varchar(MAX)
)
DECLARE #val Varchar(MAX);
INSERT INTO #temp
(CaseKey, OwnerName, Address)
SELECT ca.CApKey, DEFirstName + ' ' + DELastName, da.DAAddress1
FROM [Case] ca INNER JOIN Debtor de ON ca.CApKey = de.CApKey INNER JOIN DebtorAddress da ON ca.CApKey = da.CApKey
WHERE ca.LFpKey = #LFpKey AND de.DEIsPrimary = 1
UPDATE #temp SET Note =
(SELECT COALESCE(#val + ', ' + CANNote, CANNote)
FROM CaseNote WHERE CApKey = 51)
--SELECT #val;)
SELECT * FROM #temp
Thanks!

If i understood you correctly, you need to combine all the notes.
Get your data, queried from the 4 tables into a table (ex. #t)
Then you can use XML PATH and Stuff to achieve your goal (later you can use that for whatever your purpose as inserting to a table or display in a report etc)
SELECT CaseKey, OwnerName, Address, (STUFF((
SELECT ', ' + Note
FROM #t tx
where tx.CaseKey = t.CaseKey and tx.OwnerName = t.OwnerName and tx.Address = t.Address
FOR XML PATH('')
), 1, 2, '')
) AS StringValue
From #t t
Group by CaseKey, OwnerName, Address
Here is the fiddle

Related

TSQL: Find part of string based on a column in temp table

I need to extract the school name from a file name string. I put all of the schools in a temp table and I need to use the temp table column of SchoolName to search the string. This filename is inherited and should be a one time event to try to extract data from.
The SchoolCode and SchoolName are in the temp table. If the SchoolName matches what's in the temp table, I would like the SchoolCode as well.
I tried doing a subquery in the WHERE clause but I get an error stating it returned more than one result.
Current data:
Desired Result:
Test Code:
DROP TABLE #SchoolName
GO
CREATE TABLE #SchoolName (
FILENAME VARCHAR(MAX)
)
INSERT INTO #SchoolName
( FILENAME )
VALUES
('New Student added 10-02-16\High School\2015\North Side HS\JONES, JIMMY E_07-29-1993_2314687.PDF')
,('2006\South Side HIGH SCHOOL\GRADUATE\Johnson Jack B,03-19-1989,7123444.PDF')
,('2010\Riverwood\GRADUATES\Harmon, Kardon C_07-21-1991_370143.PDF')
,('2009\RockCreek\GRADUATES\Vandolay, Art E_09-23-1974_7210122.PDF')
DROP TABLE #SchoolsList
CREATE TABLE #SchoolsList (
SchoolCode VARCHAR(4)
,School varchar(500)
)
INSERT INTO #SchoolsList
(
SchoolCode
, School
)
VALUES
(1111 ,'North Side '),(1112 ,'South Side '),(1113 ,'Riverwood '),(1114 ,'RockCreek')
You can join to your SchoolList table using a like (assuming your school list is actually a distinct list)
SELECT l.SchoolCode, n.*
FROM #SchoolName n
LEFT OUTER JOIN #SchoolsList l
ON n.FILENAME LIKE '%' + l.School + '%'
Riverwood doesn't return a code since you have a space in the school list (SS and NS work since there is actually a space after them in both the filename and the school list)
I think you're looking for
SELECT SL.*
FROM SchoolsList SL JOIN SchoolName SN
ON SN.FileName LIKE CONCAT('%\', RTRIM(LTRIM(SL.School)), '%');
-- You can remove LTRIM() if there is no spaces in the begining
Demo

Selecting from one table and modifying it before importing

I have since modified this process and hopefully simplified. In the past, I had two tables, tablename and result. Tablename had a column (56th of 90) named cnty which was char(3). The second table, result, had a field which essentially was 000 + cnty. This field is titled area. I was trying to insert the cnty values from tablename, add the three zeros at the beginning and place them in the result table under the column, area.
Now I have both columns in result. Area is blank for now. Cnty contains the values that were in tablename (79954 of them).
Sample data
area employment busdesc cnty
410 gas station 003
Desired Result
area employment busdesc cnty
000003 410 gas station 003
Try the following query:
update dbo.result
set area = concat('000',cnty);
Hope it helps!
update res
set res.area = '000' + tbl.cnty
from Result res inner join [originalTable] tbl
on res.id=tbl.id --Don't know how to join both tables, let us know
EDIT: In regard to the last comment, let's create a new table Results2 (because I don't know all the columns in the table) This table will have all columns of tablename plus new Area column.
select *, '000' + cnty as AREA
into Results2
from dbo.tablename;
You have to specify each column or in this case an asterisk * will do
Is this the syntax you are looking for?
insert into dbo.result (name1, area)
select name1, '000' + cnty
from dbo.tablename;
Or, if the table doesn't already exist:
select name1, ('000' + cnty) as area
into dbo.result
from dbo.tablename;

sql concat within a SELECT statement

This is similiar to this one. How to concatenate all columns in a select with SQL Server
But not quite. This is MS SQL 2008. I am pulling patient demographics, and one of those is race, which is a multi-choice field (you could be asian and chinese for example). The race table 'PatientRace' is linked to the patient table by patientid. So the table structure is thus:
Patient table
PatientID
PatientName
PatientAddress
PatientRace table
PatientRaceID
PatientID (FK)
Description
I only want one row, and I want race to be concatenated. Is it possible to do this within a single SELECT statement or do I need to do a cursor? I am envisioning the cursor to be like this: Initial select for all the other demographics, insert into a temp table. Go through the temp table by patientID, then for each, grab out the race, concat, and add to the temp table.
The desired output is like this: 1 row per patient.
Name: "Joe Blow"
Race: "Asian, Chinese"
You need to use STUFF and FOR XML like this
SELECT p.PatientName,
(STUFF(SELECT ',' + r.Description
FROM PatientRace r
WHERE r.PatientID = p.PatientID
FOR XML('')), 1, 1, '')
FROM Patients p
Concatenating string values in SQL Server is not obvious. It requires using "xml" data processing and a subquery:
select p.*,
stuff((select ', ' + Description
from patientrace pr
where pr.patientid = p.patientid
for xml path ('')
), 1, 2, ''
) as races
from patients p;
As for me, you have write function like fn_GetRaceByID(int PatientID), that returns desired string. So use it in your select. Link in your question has good example, how to do this.

Pad 0's to returned query and insert into temp table

Got sql to pad 0's from: Formatting Numbers by padding with leading zeros in SQL Server
What I want to do is get a users order history from our Navigator database tables. We have a process that puts the orders from the website tables into the the navigator tables (because the orders need to be formatted for the nav table).
I want to query the website tables to get the orders from a logged in user using their user id:
SELECT OrderID FROM db1.zm.dbo.zOrder WHERE AccountID = 631180 (this returns multiple order id's)
db1 is the server, zm is database.
The OrderID's returned are formatted like 4565, 5675, ect. I want to insert them into a temp table like: Z0004565 with a Z and enough leading 0's to hit 7 digits for the number.
How do I modifiy the select statement to do so? Or can I.
SQL for padded 0's: SELECT REPLICATE('0', 7-LEN(4665)) + 4665
SQL Following Comments:
DECLARE #OrderNumTable table (orderNum varchar(20))
INSERT INTO #OrderNumTable EXEC( SELECT (''Z'' + REPLICATE(''0'', 7-len(OrderID)) + OrderID)FROM db1.zm.dbo.zOrder WHERE AccountID = 631180
SELECT OrderID,
'Z'+RIGHT('0000000'+CAST(OrderID AS VARCHAR(7)),7)
FROM db1.zm.dbo.zOrder
WHERE AccountID = 631180
Updated following the question edit
DECLARE #OrderNumTable table (orderNum varchar(8))
INSERT INTO #OrderNumTable(orderNum)
SELECT 'Z'+RIGHT('0000000'+CAST(OrderID AS VARCHAR(7)),7)
FROM db1.zm.dbo.zOrder
WHERE AccountID = 631180
Can you not just add a Z to the front?
SELECT 'Z' + REPLICATE('0', 7-LEN(OrderID)) + LTRIM(STR(OrderID))

Return multiple values in one column within a main query

I am trying to find Relative information from a table and return those results (along with other unrelated results) in one row as part of a larger query.
I already tried using this example, modified for my data.
How to return multiple values in one column (T-SQL)?
But I cannot get it to work. It will not pull any data (I am sure it is is user[me] error).
If I query the table directly using a TempTable, I can get the results correctly.
DECLARE #res NVARCHAR(100)
SET #res = ''
CREATE TABLE #tempResult ( item nvarchar(100) )
INSERT INTO #tempResult
SELECT Relation AS item
FROM tblNextOfKin
WHERE ID ='xxx' AND Address ='yyy'
ORDER BY Relation
SELECT #res = #res + item + ', ' from #tempResult
SELECT substring(#res,1,len(#res)-1) as Result
DROP TABLE #tempResult
Note the WHERE line above, xxx and yyy would vary based on the input criteria for the function. but since you cannot use TempTables in a function... I am stuck.
The relevant fields in the table I am trying to query are as follows.
tblNextOfKin
ID - varchar(12)
Name - varchar(60)
Relation - varchar(30)
Address - varchar(100)
I hope this makes enough sense... I saw on another post an expression that fits.
My SQL-fu is not so good.
Once I get a working function, I will place it into the main query for the SSIS package I am working on which is pulling data from many other tables.
I can provide more details if needed, but the site said to keep it simple, and I tried to do so.
Thanks !!!
Follow-up (because when I added a comment to the reponse below, I could not edit formatting)
I need to be able to get results from different columns.
ID Name Relation Address
1, Mike, SON, 100 Main St.
1, Sara, DAU, 100 Main St.
2, Tim , SON, 123 South St.
Both the first two people live at the same address, so if I query for ID='1' and Address='100 Main St.' I need the results to look something like...
"DAU, SON"
Mysql has GROUP_CONCAT
SELECT GROUP_CONCAT(Relation ORDER BY Relation SEPARATOR ', ') AS item
FROM tblNextOfKin
WHERE ID ='xxx' AND Address ='yyy'
You can do it for the whole table with
SELECT ID, Address, GROUP_CONCAT(Relation ORDER BY Relation SEPARATOR ', ') AS item
FROM tblNextOfKin
GROUP BY ID, Address
(assuming ID is not unique)
note: this is usually bad practice as an intermediate step, this is acceptable only as final formatting for presentation (otherwise you will end up ungrouping it which will be pain)
I think you need something like this (SQL Server):
SELECT stuff((select ',' +Relation
FROM tblNextOfKin a
WHERE ID ='xxx' AND Address ='yyy'
ORDER BY Relation
FOR XML path('')),1,1,'') AS res;