Rows to Columns in SQL Server 2000 - sql

I have this..
IDProspecto | IDObservacionCustomer | Observacion
---------------------------------------------------------
2204078 | 275214 | 03/9 Hable con Claudia me informa que Roberto ya se termino le deje..
2204078 | 294567 | 19/09 SOLICITAN LLAME MAÑANA A ALEJANDRO
2204078 | 295310 | 20/09 se envia mail a adrian
2204078 | 304102 | CIA SOLICITA NO INSTALE EQUIPO
And I want to have this...
idprospecto | observacion1 | observacion2 | observacion3 | observacion4 | observacionN
-----------------------------------------------------------------------------------------
2204078 | 03/09 Hable con clau... | 19/09 solicitan llame... | 20/09 se envia... | CIA solicita.. | ...
I read a lot about this but I found it hard to implement, since I never used cursor and pivot is not available in SQL Server 2000, I hope someone here can help me, thanks.

Since SQL Server 2000 does not have the PIVOT function, you should be able to use something similar to the following:
DECLARE #query AS NVARCHAR(4000)
DECLARE #rowCount as int
DECLARE #pivotCount as int
DECLARE #pivotRow as varchar(10)
set #rowCount = 1
set #pivotRow = ''
create table #colsPivot
(
id int IDENTITY(1,1),
name varchar(20),
CustId int
)
insert into #colsPivot
select 'Observacion', IDObservacionCustomer
from yourtable
set #pivotCount= (select COUNT(*) from #colsPivot)
-- reset rowcount
set #rowCount = 1
set #query = ''
---- create the CASE string
while #rowCount <= #pivotCount
begin
set #pivotRow = (select Top 1 CustId from #colsPivot)
set #query = #query + ', max(case when IDObservacionCustomer = ''' + #pivotRow + ''' then Observacion end) as ''Observacion_' + cast(#rowCount as varchar(10)) + ''''
delete from #colsPivot where CustId = #pivotRow
if #rowCount <= #pivotCount
begin
set #rowCount = #rowCount + 1
end
end
-- add the rest of the SQL Statement
set #query = 'SELECT IDProspecto ' + #query + ' from yourtable group by IDProspecto'
exec(#query)
See SQL Fiddle With Demo

You can try this example.
Prepare data:
create table tab1
(
IDProspecto int,
IDObservacionCustomer int,
Observacion varchar(130)
)
insert into tab1
values (2204078,275214 ,'03/9 Hable con Claudia me informa que Roberto ya se termino le deje..' )
insert into tab1
values (2204078,294567 ,'19/09 SOLICITAN LLAME MAÑANA A ALEJANDRO ' )
insert into tab1
values (2204078,295310 ,'20/09 se envia mail a adrian' )
insert into tab1
values (2204078,304102 ,'CIA SOLICITA NO INSTALE EQUIPO' )
We need identity field, so I create new table, and copy data from tab1.
create table tab2
(
id int identity,
IDProspecto int,
IDObservacionCustomer int,
Observacion varchar(130)
)
insert into tab2(IDProspecto,IDObservacionCustomer,Observacion)
select IDProspecto,IDObservacionCustomer,Observacion from tab1
Run query:
declare #max int, #inc int, #SqlSel varchar(2000),#SqlJoin varchar(2000), #Sql varchar(2000)
select #max = max(cnt) from (
select count(1) as cnt
from tab1
) T
select #inc = 1
select #SqlSel = 'select distinct t.IDProspecto '
select #SqlJoin = 'from tab2 t'
while #max>=#inc
begin
select #SqlSel= #SqlSel+', tab2'+convert(varchar,#inc)+'.Observacion as o'+convert(varchar,#inc)
select #SqlJoin = #SqlJoin+' left join tab2 as tab2'+convert(varchar,#inc)+' on t.IDProspecto = tab2'+convert(varchar,#inc)+'.IDProspecto and tab2'+convert(varchar,#inc)+'.id='+convert(varchar,#inc)
select #inc=#inc+1
end
select #SqlSel, #SqlJoin
exec( #SqlSel+' '+ #SqlJoin)

Related

Concate string into temp table in cursor

I have a temp table structure #temp2 like this
route total driverID
------------------------
10B 300
7B 400
and would like to add the driverID column with a result like 5555, 68989
to do this, I use the cursor to loop another table look like this
driverID routeNo
-------------------
5555 10B
68989 10B
72000 7B
Here is the code
declare #driverID varchar(max)
declare #routeNew varchar(20)
DECLARE brand_cursor CURSOR FOR
select distinct driver_id, route_number from [dbcwl].[dbo].[collection_deduction_summary]
where YEAR(trans_date) = #year
and MONTH(trans_date) = #month
and route_number in (select actual_route from [dbcwl].[dbo].[livedispatchingdata_pmhs_daily_summary] where status = 'OK' and YEAR(trans_date) = #year AND month(trans_date) = #month )
and vehicle_id in (select vehicle_id from [dbcwl].[dbo].[livedispatchingdata_pmhs_daily_summary] where status = 'OK' and YEAR(trans_date) = #year AND month(trans_date) = #month )
group by route_number, driver_id
OPEN brand_cursor
FETCH NEXT FROM brand_cursor
INTO #driverID, #routeNew
WHILE ##FETCH_STATUS = 0
BEGIN
--update #temp2
update #temp2 set driverID += ','+ #driverID where routeNo = #routeNew;
FETCH NEXT FROM brand_cursor
INTO #driverID, #routeNew
END
CLOSE brand_cursor;
DEALLOCATE brand_cursor;
sadly, I got the driverID column is null
and would like to have finalized temp table look like this:
route total driverID
------------------------
10B 300 5555,68989
7B 400 72000
;with cte as -- Step 1: Get all Driver Ids by routeNo
(
SELECT routeNo, driverID =
STUFF((SELECT DISTINCT ', ' + CAST(driverID AS NVARCHAR(100))
FROM #A b
WHERE b.routeNo = a.routeNo
FOR XML PATH('')), 1, 2, '')
FROM #A a
GROUP BY routeNo
)
update b -- Step 2: Update driverID accordingly.
set driverID = cte.driverID
from #B b
inner join cte on b.route = cte.routeNo
Result here
You can string_agg():
update t
set t.driverID = ot.drivers
from #temp2 t join
(select ot.routeNo, string_agg(driverID, ',') as drivers
from othertable ot
group by ot.routeNo
) ot
on t.routeNo = ot.routeNo;

Concatenate rows to one column sybase

I have limited functionality on our current database. I have a scenario where I need to Concatenate rows to one column in SYBASE
LETTER
A
B
C
D
EXPECTED RESULT
A,B,C,D
Can you please help me?
I used this form ... change for you need!
declare #w_caracter_val varchar(2),
#w_contador smallint,
#w_registros smallint,
#w_caracterFinal varchar(30)
--Crear tabla temporal
create table #sb_caracteres
(se_id int identity,
codigo varchar(10))
--insert a la tabla #
insert into #sb_caracteres
(codigo)
select codigo
from cr_corresp_sib
where tabla = 'T260'
--select * from #sb_caracteres
select #w_registros = (select count(1)from #sb_caracteres)
select #w_contador = 1
select #w_caracterFinal= ''
while #w_contador <= #w_registros
begin
select #w_caracter_val = codigo
from #sb_caracteres
where se_id = #w_contador
print 'codigo %1!, %2!', #w_contador, #w_caracter_val
--select #w_caracterFinal= concat(#w_caracterFinal,#w_caracter_val)
select #w_caracterFinal = ltrim(rtrim(#w_caracterFinal)) + ltrim(rtrim(#w_caracter_val))
select #w_caracterFinal
--print 'registros %1!', #w_caracterFinal
Select #w_contador = #w_contador +1
end

Single column from Multiple tables SQL-SERVER 2014 Exprs

I have a DB with 50 tables having the same structure (same column names, types) clustered Indexed on the Created Date column . Each of these tables have around ~ 100,000 rows and I need to pull all of them for some columns.
select * from customerNY
created date | Name | Age | Gender
__________________________________
25-Jan-2016 | Chris| 25 | M
27-Jan-2016 | John | 24 | M
30-Jan-2016 | June | 34 | F
select * from customerFL
created date | Name | Age | Gender
__________________________________
25-Jan-2016 | Matt | 44 | M
27-Jan-2016 | Rose | 24 | F
30-Jan-2016 | Bane | 34 | M
The above is an example of the tables in the DB. I need an SQL that runs quickly pulling all the data. Currently, I am using UNION ALL for this but it takes a lot of time for completing the report. Is there another way for this where I can pull in data without using UNION ALL such as
select Name, Age, Gender from [:customerNY:customerFL:]
Out of context: Can I pull in the table name in the result?
Thanks for any help. I've been putting my mind to this but I can't find a way to do it quicker.
This dynamic SQL approach should meet your criteria, it selects table names from the schema and creates a SELECT statement at runtime for it to execute, and to meet the criteria of the UNION ALL each SELECT statement is given a UNION ALL then I use STUFF to remove the first one.
DECLARE #SQL AS VarChar(MAX)
SET #SQL = ''
SELECT #SQL = #SQL + 'UNION ALL SELECT Name, Age, Gender FROM ' + TABLE_SCHEMA + '.[' + TABLE_NAME + ']' + CHAR(13)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'Customer%'
SELECT #SQL = STUFF(#SQL,1,10,'')
EXEC (#SQL)
However I do not recommend using this and you should do what people have suggested in the comments to restructure your data.
Memory Optimising the test tables below gave a 7x speed increase compared to the same data in regular tables. Samples are 50 tables of 100000 rows. Please only run this on a test server as it creates filegroups/tables etc.:
USE [master]
GO
ALTER DATABASE [myDB] ADD FILEGROUP [MemOptData] CONTAINS MEMORY_OPTIMIZED_DATA
GO
ALTER DATABASE [myDB] ADD FILE ( NAME = N'Mem', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA' ) TO FILEGROUP [MemOptData] --Change Path for your version
Go
use [myDB]
go
set nocount on
declare #loop1 int = 1
declare #loop2 int = 1
declare #NoTables int = 50
declare #noRows int = 100000
declare #sql nvarchar(max)
while #loop1 <= #NoTables
begin
set #sql = 'create table [MemCustomer' + cast(#loop1 as nvarchar(6)) + '] ([ID] [int] IDENTITY(1,1) NOT NULL,[Created Date] date, [Name] varchar(20), [Age] int, Gender char(1), CONSTRAINT [PK_Customer' + cast(#loop1 as nvarchar(6)) + '] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)'
exec(#sql)
while #loop2 <= #noRows
begin
set #sql = 'insert into [MemCustomer' + cast(#loop1 as nvarchar(6)) + '] ([Created Date], [Name], [Age], [Gender]) values (DATEADD(DAY, ROUND(((20) * RAND()), 0), DATEADD(day, 10, ''2018-06-01'')), (select top 1 [name] from (values(''bill''),(''steve''),(''jack''),(''roger''),(''paul''),(''ozzy''),(''tom''),(''brian''),(''norm'')) n([name]) order by newid()), FLOOR(RAND()*(85-18+1))+18, iif(FLOOR(RAND()*(2))+1 = 1, ''M'', ''F''))'
--print #sql
exec(#sql)
set #loop2 = #loop2 + 1
end
set #loop2 = 1
set #loop1 = #loop1 + 1
end
;with cte as (
Select * from MemCustomer1
UNION
Select * from MemCustomer2
UNION
...
UNION
Select * from MemCustomer50
)
select * from cte where [name] = 'tom' and age = 27 and gender = 'F'

Concatenate champ name1

I have a table with champ: Letter1, Letter2, Letter3 ... until 6.
Structure of my table:
TYPEID | BenefitsID | Letter1 | Coef1 | Letter2 | Letter3 | Coef3 | Letter4 | Coef4 | Letter5 | Coef5 | Letter6 | Coef6 | Resultat
I want to make a select request in WHILE loop like this :
#count =1;
While (#count<7)
begin
#letter = **(select letter+#count from ....)**
..
end
The result I want is to select the value of Letter1, Letter2... and Coef1, Coef2 ... and multiply them to insert them in champ Resultat
My question is how to select Letter1, Letter2, ... in one request. Will the bold request works? Or should I use something else?
I used SQL server 2008..
Assuming you are using MySQL, do you want something like this?
select concat(letter, (#count := #count + 1)
from t cross join
(select #count := 0) params
order by ??
limit 7;
As I commented, numerated columns are good indication for a bad design.
Being that said, dynamic SQL will answer your need.
declare #count int = 1
,#stmt nvarchar(max)
While (#count<7)
begin
set #stmt = 'select Letter' + cast(#count as varchar(10)) + ' from mytable'
exec sp_executesql #stmt
set #count = #count + 1
end

Join table using columns which contains other table's id's separated by commas

I have FACULTY table which contain the column with other table's id's separated by commas. I want to join those with respective table.
faculty table:
id | name | course_id | subject_id
a | smith | 2,3 | 1,2
course table:
id | name
1 | bcom
2 | mcom
3 | bba
subject table:
id | name
1 | account
2 | state
3 | economics
I want to get result from these table like..
faculty.id, faculty.name, course.name(using faculty.course_id), subject.name(using faculty.subject_id)
I have tried a lot of queries and also finds from Google but it didn't gave me proper result.
I do not think the performance will be too nice but worths trying. This solution would work in SQL SERVER:
SELECT *
FROM faculty F
JOIN course C
ON ','+F.course_id+',' LIKE '%,'+CONVERT(VARCHAR,C.ID) +',%'
JOIN subject S
ON ','+F.subject_id_id+',' LIKE '%,'+CONVERT(VARCHAR,S.ID) +',%'
Based on Albin Sunnanbo's comment i would also sugget you add some many too many tables:
fcourses
facultyId
courseId
and
fsubjects
facultyId
subjectId
That way you could do a proper join :
SELECT *
FROM faculty F
JOIN fcourses FC
ON F.Id = FC.facultyId
JOIN course C
ON FC.courseId = C.ID
JOIN fsubjects FS
ON F.Id = FS.facultyId
JOIN subject S
ON FS.courseId = S.ID
You can do the following query
select * from faculty F
JOIN course C
on CHARINDEX((','+CAST(c.id as varchar(10))+','), (','+f.courseid+',')) > 0
JOIN subject s
on CHARINDEX((','+CAST(s.id as varchar(10))+','), (','+f.subjectid+',')) > 0
I've done something similar like this:
select f.id, f.lname, f.fname, U.useridlist
from TABLE1 F, TABLE2 U
where ',' || U.useridlist || ',' like '%,' || f.id || ',%'
If you can create a 'string to int table' function, I would look at the following:
Create the function
CREATE FUNCTION [dbo].[udf_ConvertIntListToTable] (#list varchar(MAX))
RETURNS #tbl TABLE (val int) AS
BEGIN
DECLARE #ix int,
#pos int,
#str varchar(MAX),
#num int
SET #pos = 1
SET #ix = 1
WHILE #ix > 0
BEGIN
SET #ix = charindex(',', #list, #pos)
IF #ix > 0
SET #str = substring(#list, #pos, #ix - #pos)
ELSE
SET #str = substring(#list, #pos, len(#list))
SET #str = ltrim(rtrim(#str))
IF #str LIKE '%[0-9]%' AND
(#str NOT LIKE '%[^0-9]%' OR
#str LIKE '[-+]%' AND
substring(#str, 2, len(#str)) NOT LIKE '[-+]%[^0-9]%')
BEGIN
SET #num = convert(int, #str)
INSERT #tbl (val) VALUES(#num)
END
SET #pos = #ix + 1
END
RETURN
END
Then query using CROSS APPLY
declare #FacultyTable table(id int PRIMARY KEY, name nvarchar(50), course_id varchar(50))
declare #CourseTable table(id int PRIMARY KEY, name nvarchar(50))
insert into #FacultyTable values(1, 'Peter Sagal', '11,22')
insert into #FacultyTable values(2, 'Carl Kasell', '22,33')
insert into #CourseTable values(11,'News')
insert into #CourseTable values(22,'News')
insert into #CourseTable values(33,'News')
insert into #CourseTable values(44,'News')
select *
from #FacultyTable f
CROSS APPLY(
SELECT *
FROM #CourseTable c
WHERE
c.id IN (SELECT * FROM dbo.udf_ConvertIntListToTable(f.course_id))
) tCourses