Concatenate champ name1 - sql

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

Related

SQL pivot table1 into table2 without using dynamic SQL pivot or hardcode query

I have seen many questions and answers given about pivoting table with SQL, with dynamic SQL pivot or hard code query with CASE WHEN.
However is there any way I can pivot table without using those 2?
Table 1:
| col1 | col2 | col3 |
|--------|-------|--------|
| ABCD | 1 | XY123 |
| ABCD | 2 | RT789 |
| PQST | 3 | XY123 |
| PQST | 4 | RT789 |
Pivoting to
| col1 | ABCD | PQST |
|--------|-------|-------|
| XY123 | 1 | 3 |
| RT789 | 2 | 4 |
My idea was to retrieve the structure of the col with:
WITH
structure AS (
SELECT DISTINCT
col3 AS col1, col1 AS colName, col2 AS values
FROM table1 ori
)
and then extracting matched values of each cell with joins and storing them temporarily. At last JOIN again populating them in the output. However I am stuck after the above step. I can't use PIVOT and have to do this dynamically (i.e. can't use the method to hardcode each value with CASE WHEN)
How can I achieve this?
This is not as efficient (and not as easy to code) as a dynamic pivot. However, it is doable.
It does all need to be dynamic e.g., creating each SQL statement as a string and executing that.
The process involves
Determine the column names (store in a temporary table)
Creating the table with the first column only
Populating that first column
For each additional column name
Adding a column to the table (dynamically)
Populating that column with data
You haven't specified the database - I'll illustrate the following below using SQL Server/T-SQL.
The following are in this db<>fiddle so you can see what's going on.
CREATE TABLE #ColNames (ColNum int IDENTITY(1,1), ColName nvarchar(100), ColNametxt nvarchar(100));
INSERT INTO #ColNames (ColName, ColNametxt)
SELECT DISTINCT QUOTENAME(Col1), Col1
FROM table1;
This will populate the #ColNames table with the values 1, [ABCD], ABCD, 2, [PQST], PQST.
The next step is to create your output table - I'll call it #pvttable
CREATE TABLE #pvttable (col1 nvarchar(100) PRIMARY KEY);
INSERT INTO #pvttable (col1)
SELECT DISTINCT Col3
FROM table1;
This creates your table with 1 column (col1) with values XY123 and RT789).
The write your favorite loop (e.g., cursor, while loop). In each step
Get the next column name
Add the column to the table
Update that column with appropriate data
e.g., the following is an illustrative example with your data.
DECLARE #CustomSQL nvarchar(4000);
DECLARE #n int = 1;
DECLARE #ColName nvarchar(100);
DECLARE #ColNametxt nvarchar(100);
SELECT #ColName = ColName,
#ColNameTxt = ColNameTxt
FROM #ColNames
WHERE ColNum = #n;
WHILE #ColName IS NOT NULL
BEGIN
SET #CustomSQL = N'ALTER TABLE #pvttable ADD ' + #ColName + N' nvarchar(100);';
EXEC (#CustomSQL);
SET #CustomSQL =
N'UPDATE #pvttable SET ' + #Colname + N' = table1.col2'
+ N' FROM #pvttable INNER JOIN table1 ON #pvttable.col1 = table1.col3'
+ N' WHERE table1.col1 = N''' + #ColNametxt + N''';';
EXEC (#CustomSQL);
SET #n += 1;
SET #ColName = NULL;
SET #ColNametxt = NULL;
SELECT #ColName = ColName,
#ColNameTxt = ColNameTxt
FROM #ColNames
WHERE ColNum = #n;
END;
SELECT * FROM #pvttable;

Sql Server Split a string to a table using

I have a string : Brand=b1-b2&Vendor=v1-v2-v3&CustomField=cf1-cf2-cf3
I want to make a table..
**Name** | **Value**
------------- | ------
Brand | b1
Brand | b2
Vendor | v1
Vendor | v2
Vendor | v3
CustomField | cf1
CustomField | cf2
CustomField | cf3
Thanks for your help
Edit Note : I tried, but I do not think it's performance
CREATE PROCEDURE [dbo].[SplitTableInStr]
(
#StrParameter NVARCHAR(MAX)
)
AS
BEGIN
DECLARE #Delimiter CHAR = '&',
#Index SMALLINT,
#Start SMALLINT,
#DelSize SMALLINT;
SET #DelSize = LEN(#Delimiter);
CREATE TABLE #FilteredItems
(
[Key] NVARCHAR(400),
[Values] NVARCHAR(MAX)
)
WHILE LEN(#StrParameter) > 0
BEGIN
SET #Index = CHARINDEX(#Delimiter, #StrParameter)
IF #Index = 0
BEGIN
DECLARE #Key NVARCHAR(400) = SUBSTRING(#StrParameter, 1, CHARINDEX('=', #StrParameter) - 1);
DECLARE #Values NVARCHAR(MAX) = SUBSTRING(#StrParameter, CHARINDEX('=', #StrParameter) + 1, LEN(#StrParameter));
INSERT INTO #FilteredItems ([Key],[Values])
VALUES (#Key,#Values)
BREAK
END
ELSE
BEGIN
DECLARE #IndexItem NVARCHAR(MAX) = SUBSTRING(#StrParameter, 1, #Index - 1);
DECLARE #IndexKey NVARCHAR(400) = SUBSTRING(#IndexItem, 1, CHARINDEX('=', #IndexItem) - 1);
DECLARE #IndexValues NVARCHAR(MAX) = SUBSTRING(#IndexItem, CHARINDEX('=', #IndexItem) + 1, LEN(#IndexItem));
INSERT INTO #FilteredItems ([Key],[Values])
VALUES (#IndexKey,#IndexValues)
SET #Start = #Index + #DelSize
SET #StrParameter = SUBSTRING(#StrParameter, #Start , LEN(#StrParameter) - #Start + 1)
END
END
DECLARE #KeyBase NVARCHAR(400),
#ValueBase NVARCHAR(MAX);
CREATE TABLE #DisplayOrderTmp
(
[EndName] NVARCHAR(400),
[EndValue] NVARCHAR(400)
)
WHILE EXISTS(SELECT * From #FilteredItems)
BEGIN
SELECT TOP 1 #KeyBase = [Key], #ValueBase = [Values] FROM #FilteredItems
DECLARE #OptionDelimiter CHAR = '-',
#OptionIndex SMALLINT,
#OptionStart SMALLINT,
#OptionDelSize SMALLINT;
SET #OptionDelSize = LEN(#OptionDelimiter)
WHILE LEN(#ValueBase) > 0
BEGIN
SET #OptionIndex = CHARINDEX(#OptionDelimiter, #ValueBase)
IF #OptionIndex = 0
BEGIN
INSERT INTO #DisplayOrderTmp VALUES (#KeyBase, #ValueBase)
BREAK;
END
ELSE
BEGIN
INSERT INTO #DisplayOrderTmp VALUES (#KeyBase, SUBSTRING(#ValueBase, 1, CHARINDEX(#OptionDelimiter, #ValueBase) - 1))
SET #OptionStart = #OptionIndex + #OptionDelSize
SET #ValueBase = SUBSTRING(#ValueBase, #OptionStart , LEN(#ValueBase) - #OptionStart + 1)
END
END
DELETE #FilteredItems WHERE [Key] = #KeyBase
END
SELECT * FROM #DisplayOrderTmp;
END
EXEC dbo.[SplitTableInStr] 'Brand=b1-b2&Vendor=v1-v2-v3&CustomField=cf1-cf2-cf3'
using a CSV Splitter table valued function by Jeff Moden with cross apply()
declare #s nvarchar(4000) = 'Brand=b1-b2&Vendor=v1-v2-v3&CustomField=cf1-cf2-cf3';
select
Name = left(s.Item,charindex('=',s.Item)-1)
, Value = i.Item
from dbo.DelimitedSplitN4k(#s,'&') s
cross apply dbo.DelimitedSplitN4k(replace(s.Item,'=','-'),'-') i
where i.ItemNumber > 1
rextester demo: http://rextester.com/RTAT28301
returns:
+-------------+------+
| Name | Item |
+-------------+------+
| Brand | b1 |
| Brand | b2 |
| Vendor | v1 |
| Vendor | v2 |
| Vendor | v3 |
| CustomField | cf1 |
| CustomField | cf2 |
| CustomField | cf3 |
+-------------+------+
splitting strings reference:
Tally OH! An Improved SQL 8K “CSV Splitter” Function - Jeff Moden
Splitting Strings : A Follow-Up - Aaron Bertrand
Split strings the right way – or the next best way - Aaron Bertrand
string_split() in SQL Server 2016 : Follow-Up #1 - Aaron Bertrand
I think you should get the best performance with CLR function (in C#) for this purpose:
https://msdn.microsoft.com/en-us/library/ms131103.aspx
You might manually split the input or create compiled Regex with named groups to parse input values.

Find a value from all table columns

I am building a functionality that will filter a data on all column table.
Let's say I have this table:
-------------------------------------
| ID | NAME | Address | Remarks |
| 1 | Manny | Phil | Boxer-US |
| 2 | Timothy | US | Boxer |
| 3 | Floyd | US | Boxer |
| 4 | Maidana | US | Boxer |
| 5 | Marquez | MEX | Boxer |
-------------------------------------
I search for "US", it should give me IDs 1-4 since "US" exists in their columns.
I could have this to filter it:
SELECT ID FROM tbl_Boxers
WHERE ID LIKE '%US%' OR NAME LIKE '%US%' OR Address LIKE '%US%' OR Remarks LIKE '%US%'
But I'm trying to avoid a long WHERE clause here since in actual, I have around 15 columns to look at.
Is there any other way to minimize the where clause?
Please help.
Thanks
The way this is normally done is to make a 'Searchable Field' column where you concatinate all search columns into one field for searching.
So while that provides an easier overview and querying it adds some management of the data you need to be aware off on inserts and updates.
Also on its own - it's not an optimal way of searching, so if performance is important - then you should look to implement full text search.
So the question is where you want to have the 'overhead' and whether that functionality your building is going to be run often or just once in a while.
If it is the former, and performance is important - look to full text. If it is just a once-in-a-while query, then I'd properly just do the long WHERE clause myself to avoid adding more overhead on the maintenance of the data
Check the following solution. Here the query is generated dynamically based on the column names in your table.
This is applicable if the given table is a physical table. This solution wont work for temporary tables or table variables.
BEGIN TRAN
--Simulate your table structure
--Should be a physical table. Cannot be a temp table or a table variable
CREATE TABLE TableA
(
ID INT,
NAME VARCHAR(50),
ADDRESS VARCHAR(50),
REMARKS VARCHAR(50)
)
--Added values for testing
INSERT INTO TableA(ID, name , address ,remarks) VALUES(1,'Manny','Phil','Boxer-US')
INSERT INTO TableA(ID, name , address ,remarks) VALUES(2,'Timothy','US','Boxer')
INSERT INTO TableA(ID, name , address ,remarks) VALUES(3,'Floyd','US','Boxer')
INSERT INTO TableA(ID, name , address ,remarks) VALUES(4,'Maidana','US','Boxer')
INSERT INTO TableA(ID, name , address ,remarks) VALUES(5,'Marquez',' MEX','Boxer')
--Solution Starts from here
DECLARE #YourSearchValue VARCHAR(50)--Will be passed
SET #YourSearchValue = 'US' --Simulated passed value
CREATE TABLE #TableCols
(
ID INT IDENTITY(1,1),
COLUMN_NAME VARCHAR(1000)
)
INSERT INTO #TableCols
(COLUMN_NAME)
SELECT COLUMN_NAME
FROM information_schema.columns
WHERE table_name = 'TableA';
DECLARE #STARTCOUNT INT, #MAXCOUNT INT, #COL_NAME VARCHAR(1000), #QUERY VARCHAR(8000), #SUBQUERY VARCHAR(8000)
SELECT #STARTCOUNT = 1, #MAXCOUNT = MAX(ID) FROM #TableCols;
SELECT #QUERY = '', #SUBQUERY = ''
WHILE(#STARTCOUNT <= #MAXCOUNT)
BEGIN
SELECT #COL_NAME = COLUMN_NAME FROM #TableCols WHERE ID = #STARTCOUNT;
SET #SUBQUERY = #SUBQUERY + ' CONVERT(VARCHAR(50), ' + #COL_NAME + ') LIKE ''%' + #YourSearchValue + '%''' + ' OR ';
SET #STARTCOUNT = #STARTCOUNT + 1
END
SET #SUBQUERY = LEFT(#SUBQUERY, LEN(#SUBQUERY) - 3);
SET #QUERY = 'SELECT * FROM TableA WHERE 1 = 1 AND (' + #SUBQUERY + ')'
--PRINT (#QUERY);
EXEC (#QUERY);
ROLLBACK
Hope this helps.

How can I add a character into a specified position into string in SQL SERVER?

I have a varchar field like:
195500
122222200
I need to change these values to:
1955.00
1222222.00
try this
Declare #s varchar(50) = '1234567812333445'
Select Stuff(#s, Len(#s)-1, 0, '.')
--> 12345678123334.45
fiddle demo
Query:
SELECT col,
LEFT(col,len(col)-2) + '.' + RIGHT(col,2) as newcol
FROM Table1
Result:
| COL | NEWCOL |
|-----------|------------|
| 195500 | 1955.00 |
| 122222200 | 1222222.00 |
If you want to add a '.' before the last two digits of your values you can do:
SELECT substring(code,0,len(code)-1)+'.'+substring(code,len(code)-1,len(code))
FROM table1;
sqlfiddle demo
Please try:
select
Col,
REVERSE(STUFF(REVERSE(Col), 1, 2, LEFT(REVERSE(Col), 2)+'.'))
from YourTable
SQL Fiddle Demo
CREATE TABLE #T ( Value VARCHAR(20) )
INSERT INTO #T ( Value ) VALUES ( 195500 ), ( 122222200)
SELECT
Value
, NewValue = CONVERT(DECIMAL(17,2),CONVERT(DECIMAL,Value) / 100)
FROM #T
| Value | NewValue |
|-----------|------------|
| 195500 | 1955.00 |
| 122222200 | 1222222.00 |
Please Try :
select reverse(stuff(reverse(columnName),3,0,'.') ) from yourTable
Ran into something similar and came up with this, could probably change this to a function/SP to make it reusable. Scenario faced was inserting a specified character at different positions within the string, for a certain number of times.
/*
--- passed in string or column, N'C4CB6B22250B'
--- desired output, C4:CB:6B:22:25:0D
--- Test values
--- declare #strToChange varchar(50) = N'C4:CB:6B:22:25:0B'
--- declare #strToChange varchar(50) = N'C4CB6B22250B'
*/
declare #strToChange varchar(50) = N'C4CB6B22250B'
IF(SELECT LEN(#strToChange) - LEN(REPLACE(#strToChange, ':', ''))) > 0
BEGIN
---returns count of specified char
SELECT LEN(#strToChange) - LEN(REPLACE(#strToChange, ':', ''))
END
ELSE
BEGIN
declare #charCount int = 5; --# of times to insert the char
declare #shiftPosition int = 2; -- inital insertion shift
While(#charCount > 0)
begin
SET #strToChange = LEFT(#strToChange,len(#strToChange)- #shiftPosition) + ':' + RIGHT(#strToChange,#shiftPosition)
SET #charCount = #charCount - 1 --decrement charCount for each added char
SET #shiftPosition = #shiftPosition + 3 ---increment shift position by 3 for the new char and the chars that were already there
end
SELECT #strToChange
END
Please see the following code. You can choose the symbols and index in variable.
declare #index int,#sym varchar(10)
set #sym='#'
set #index=2
select left(195500,#index) +''+#sym+''+right(195500,len(195500)-#index)
declare #a varchar(10) = 'aaa'
select concat(#a,'.00')

Rows to Columns in SQL Server 2000

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)