One particular field in the SQL Table has a value in the below format.
Value11,value12,Value13
Value21,value22,value23
...
...
I need to get each of the above lines in the text into individual lines using SSRS.
for example I will get 2 rows in the report for above data.
Is there a way to do this using a reporting project in VS or Report builder?
Thanks in advance.
Update
Hi,Below is the DDL for the table
tblTest
[id] int
[Description] VARCHAR(MAX)
Lets assume there is only one record with Below
Insert Into tblTest
([id],[Description])
VALUES
(1, 'Value11,value12,Value13
Value21,value22,value23')
So there is a carriage return Caharacter in above Insert for the Description column. This will have 2 lines in the description row.
So my requirement is that when i retrieve the data, I should get into below format.
ID, Description
1, Value11,value12,Value13
1, Value21,value22,value23
You can use this SELECT for passing data to Reporting Services.
SELECT t1.id, t2.splittedDescriptions
FROM
(
SELECT tblTest.id,
CAST('<row>' + REPLACE(tblTest.[Description], CHAR(13) + CHAR(10), '</row><row>') + '</row>' AS XML) as xmlRow
FROM tblTest
) t1
CROSS APPLY
(
SELECT xmlTable.splittedRow.value('.', 'VARCHAR(MAX)') as splittedDescriptions
FROM t1.xmlRow.nodes('/row') AS xmlTable(splittedRow)
) t2
It uses XML and nodes() method to split your description when it finds a CRLF.
It work with a single CRLF, if you need to work with double CRLF you can simply modify the SELECT.
Example - input data:
INSERT INTO tblTest ([id],[Description]) VALUES
(1, 'val11, val12, val13' + CHAR(13) + CHAR(10) + 'val21, val22, val23')
INSERT INTO tblTest ([id],[Description]) VALUES
(2, 'val31, val32, val33')
INSERT INTO tblTest ([id],[Description]) VALUES
(3, 'val41, val42, val43' + CHAR(13) + CHAR(10) + 'val51, val52, val53' + CHAR(13) + CHAR(10) + 'val61, val62, val63')
Example - output:
id splittedDescriptions
----------- --------------------
1 val11, val12, val13
1 val21, val22, val23
2 val31, val32, val33
3 val41, val42, val43
3 val51, val52, val53
3 val61, val62, val63
use this,
select '1' as Id, Value11+','+value12+','+Value13 as Description into tblTest from XYZ;
Value11,value12,Value13 all should be in String
Related
I have one string element, for example : "(1111, Tem1), (0000, Tem2)" and hope to generate a data table such as
var1
var2
1111
Tem1
0000
Tem2
This is my code, I created the lag token and filter with odd rows element.
with var_ as (
select '(1111, Tem1), (0000, Tem2)' as pattern_
)
select tbb1.*, tbb2.result_string as result_string_previous
from(
select tb1.*,
min(token) over(partition by 1 order by token asc rows between 1 preceding and 1 preceding) as min_token
from
table (
strtok_split_to_table(1, var_.pattern_, '(), ')
returns (outkey INTEGER, token INTEGER, result_string varchar(20))
) as tb1) tbb1
inner join (select min_token, result_string from tbb1) tbb2
on tbb1.token = tbb2.min_token
where (token mod 2) = 0;
But it seems that i can't generate new variables in "from" step and applied it directly in "join" step.
so I wanna ask is still possible to get the result what i want in my procedure? or is there any suggestion?
Thanks for all your assistance.
I wouldn't split / recombine the groups. Split each group to a row, then split the values within the row, e.g.
with var_ as (
select '(1111, Tem1), (0000, Tem2)' as pattern_
),
split1 as (
select trim(leading '(' from result_string) as string_
from
table ( /* split at & remove right parenthesis */
regexp_split_to_table(1, var_.pattern_, '\)((, )|$)','c')
returns (outkey INTEGER, token_nbr INTEGER, result_string varchar(256))
) as tb1
)
select *
from table(
csvld(split1.string_, ',', '"')
returns (var1 VARCHAR(16), var2 VARCHAR(16))
) as tb2
;
I have an SSRS parameter that allows to select multiple values of type varchar.
How can I get my where clause to show all those selected in the parameter. An example is if the parameter choices were
1 : Rob
2 : Tom
3 : Rick
If the first two choices were selected, there should be 2 records. Something to the effect:
where Employee.Code + ' : ' + Employee.Name IN ("1 : Rob","2 : Tom")
If the parameter value is returning both the "employee code" and "employee name", then I'd use a CTE (Common Table Expression) to create the concatenated column before filtering it. You may want to create the CTE in a view if you're going to use it elsewhere.
WITH
employee
AS
(
SELECT tbl.* FROM (VALUES
( 1, 'Rob')
, ( 2, 'Tom')
, ( 3, 'Rick')
) tbl ([code], [name])
)
,
employee_values
AS
(
SELECT
[code]
, [name]
, [code_name] = CAST([code] AS VARCHAR) + ' : ' + [name]
FROM
employee
)
SELECT
[code]
, [name]
, [code_name]
FROM
employee_values
WHERE
[code_name] IN(#Employee_Code)
I've got a report that has 6 parameters. All parameters need to be optional and 3 have to be multi-value. One of the optional parameters is a dropdown, the rest are manually keyed in text boxes.
The Where clause below works when there are multiple #VendorNum values and one #FullJA value, but fails with multiple #FullJA values regardless of the #VendorNum count.
Parameters:
#VendorNum - keyed manually by user (space delimited) - optional, can be multivalue
#FullJA - keyed manually by user (space delimited) - optional, can be multivalue
#BU - optional, can be multivalue - when #JA is populated, this will auto-populate, if #JA isn't populated it's a dropdown with all selected.
#JA3 - keyed by user - optional, single value
#StartDate and #EndDate - optional single values
select * from some_table
WHERE
/*FULL JA*/
(
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND LEFT(JA, 7) IN (#FullJA)
AND BU IN(#BU)
AND #JA3 IS NULL
)
OR
/*DATE RANGE*/
(
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND LEN(ISNULL(CONVERT(VARCHAR(20), Cleared_When), '0')) >= #ClearedOnly
AND ad.Audit_Publish_Date >= ISNULL(#StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(#EndDate, '2025-12-31')
AND BU IN (#BU)
AND #FullJA IS NULL
AND #JA3 IS NULL
)
/*BUS UNIT AND JA3*/
OR (
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND BU IN (#BU)
AND ad.Audit_Publish_Date >= ISNULL(#StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(#EndDate, '2025-12-31')
AND LEFT(JA, 3) = (#JA3)
AND #FullJA IS NULL
)
/*BUS UNIT ONLY*/
OR (
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND BU IN (#BU)
AND ad.Audit_Publish_Date >= ISNULL(#StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(#EndDate, '2025-12-31')
AND #JA3 IS NULL
AND #FullJA IS NULL
)
The dataset parameter values for #FullJA and #VendorNum are both
=IIF(InStr(Parameters!FullJA.Value," ")>0,SPLIT(Parameters!FullJA.Value," "),Parameters!FullJA.Value) and all params are set as NOT multivalue, with nulls allowed.
Any help would be greatly appreciated. I've written over 200 reports for this project and this is the only one that is really grinding my gears!
Thanks!
I would approach this by building up some temp tables / table variables, to hold the potentially multi-valued variables, and then joining to those tables. This has the advantage of you being able to insert all possible values, in the case they have omitted the variable. So, you'd split your strings and put them into those tables (something along the lines of this example) if given the variable, and otherwise just do an insert into to populate your temp table / table variable.
For a split function, I prefer something like this:
create FUNCTION [dbo].[Split] (#sep VARCHAR(32), #s VARCHAR(MAX))
RETURNS TABLE
AS
RETURN
(
SELECT r.value('.','VARCHAR(MAX)') as Item
FROM (SELECT CONVERT(XML, N'<root><r>' + REPLACE(REPLACE(REPLACE(#s,'& ','& '),'<','<'), #sep, '</r><r>') + '</r></root>') as valxml) x
CROSS APPLY x.valxml.nodes('//root/r') AS RECORDS(r)
)
GO
GRANT SELECT
ON OBJECT::[dbo].[Split] TO PUBLIC
AS [dbo];
I would then put those variables into a table using something like this (my separator is a ", "):
select ltrim(rtrim(ppl.Item)) as PersonName
into #gppl
from dbo.Split(', ', #PersonListForCompare) as ppl
You would do something more like:
select ltrim(rtrim(vnd.Item)) as VendorNum
into #vendorNums
from dbo.Split(', ', #VendorNum) as vnd
You would then join to that temp table just like any other table & use it to limit your results that way. In your case, you want to put in all vendors (possibly) if they didn't give you any input. So, you'd do something like:
create table #vendorNums (VendorName varchar(64)) --I have no idea, here, what this data looks like
if #VendorNum is not null and datalength(#VendorNum) > 0
insert into into #vendorNums (VendorNum)
select ltrim(rtrim(vnd.Item))
from dbo.Split(', ', #VendorNum) as vnd
else
insert into into #vendorNums (VendorNum)
select VendorNum
from dbo.Vendors
That said, I think that you could use your select from dbo.Split directly as a table in a join, rather than putting it into the temp table. Only problem would be you'd have to be sure you had data in there to split, or else you're going to have a bunch of combinations to get the right match-up of null parameters vs. filled ones.
I am using MySQL database.
I have a CUST_INV_DET table where I have data in below format
---------------------------
CUSTOMER_ID CUSTOMER_NO
---------------------------
1 1983,1988,1989
2 2014,2011,2010
3 3012,3059,3045
---------------------------
And there is another table. NEW_CUSTOMER_NO_FORMAT
--------------------------------------
OLD_CUSTOMER_NO NEW_CUSTOMER_NO
--------------------------------------
1983 C1983-01
1988 C1988-03
1989 C1989-06
2014 C2014-01
2011 C2011-02
2010 C2010-02
3012 C3012-03
3059 C3059-23
3045 C3045-09
Can anybody suggest me on how to map CUST_INV_DET.CUSTOMER_NO in a new format by doing lookup from NEW_CUSTOMER_NO_FORMAT Table.
I know I need to use cursor but inside cursor below section I am clueless how to map since it's a comma separated value.
Do I need one more cursor inside NO_MORE_DATA =0 ?
IF (NO_MORE_DATA = 0) THEN
//MAP OLD TO NEW FORMAT HERE
END IF;
Below are the insert script
CREATE TABLE CUST_INV_DET(
CUSTOMER_ID INT(11) AUTO_INCREMENT PRIMARY KEY,
CUSTOMER_NO VARCHAR(500)
);
INSERT INTO CUST_INV_DET(CUSTOMER_NO) VALUES
('1983,1988,1989'),
('2014,2011,2010'),
('3012,3059,3045');
CREATE TABLE NEW_CUSTOMER_NO_FORMAT (
OLD_CUSTOMER_NO VARCHAR(500),
NEW_CUSTOMER_NO VARCHAR(500)
);
INSERT INTO NEW_CUSTOMER_NO_FORMAT VALUES
('1983','C1983-01'),
('1988','C1988-03'),
('1989','C1989-06'),
('2014','C2014-01'),
('2011','C2011-02'),
('2010','C2010-02'),
('3012','C3012-03'),
('3059','C3059-23'),
('3045','C3045-09');
Below is the final output I am looking for
CUSTOMER_ID CUSTOMER_NO
1 'C1983-01,C1988-03,C1989-06'
2 'C2014-01,C2011-02,C2010-02'
3 'C3012-03,C3059-23,C3045-09'
select
CUSTOMER_ID,
substring(Customer_no,0,charindex(',',Customer_no,1)) col1,
substring(Customer_no,charindex(',',Customer_no,1) + 1,charindex(',',Customer_no,1)-1) col2,
substring(Customer_no,charindex(',',Customer_no,1) + len(substring(Customer_no,charindex(',',Customer_no,1) + 1,charindex(',',Customer_no,1)-1) )+2,charindex(',',Customer_no,1)-1) col3
into #Temp2
from CUST_INV_DET
SELECT T. CUSTOMER_ID,
NCD1.NEW_CUSTOMER_NO + ',' + NCD2.NEW_CUSTOMER_NO + ',' + NCD3.NEW_CUSTOMER_NO
FROM #Temp2 T
INNER JOIN NEW_CUSTOMER_NO_FORMAT NCD1 ON NCD1.OLD_CUSTOMER_NO = T.col1
INNER JOIN NEW_CUSTOMER_NO_FORMAT NCD2 ON NCD2.OLD_CUSTOMER_NO = T.col2
INNER JOIN NEW_CUSTOMER_NO_FORMAT NCD3 ON NCD3.OLD_CUSTOMER_NO = T.col3
There is a SQL table mytable that has a column mycolumn.
That column has text inside each cell. Each cell may contain "this.text/31/" or "this.text/72/" substrings (numbers in that substrings can be any) as a part of string.
What SQL query should be executed to display a list of unique such substrings?
P.S. Of course, some cells may contain several such substrings.
And here are the answers for questions from the comments:
The query supposed to work on SQL Server.
The prefered output should contain the whole substring, not the numeric part only. It actually could be not just the number between first "/" and the second "/".
And it is varchar type (probably)
Example:
mycolumn contains such values:
abcd/eftthis.text/31/sadflh adslkjh
abcd/eftthis.text/44/khjgb ljgnkhj this.text/447/lhkjgnkjh
ljgkhjgadsvlkgnl
uygouyg/this.text/31/luinluinlugnthis.text/31/ouygnouyg
khjgbkjyghbk
The query should display:
this.text/31/
this.text/44/
this.text/447/
How about using a recursive CTE:
CREATE TABLE #myTable
(
myColumn VARCHAR(100)
)
INSERT INTO #myTable
VALUES
('abcd/eftthis.text/31/sadflh adslkjh'),
('abcd/eftthis.text/44/khjgb ljgnkhj this.text/447/lhkjgnkjh'),
('ljgkhjgadsvlkgnl'),
('uygouyg/this.text/31/luinluinlugnthis.text/31/ouygnouyg'),
('khjgbkjyghbk')
;WITH CTE
AS
(
SELECT MyColumn,
CHARINDEX('this.text/', myColumn, 0) AS startPos,
CHARINDEX('/', myColumn, CHARINDEX('this.text/', myColumn, 1) + 10) AS endPos
FROM #myTable
WHERE myColumn LIKE '%this.text/%'
UNION ALL
SELECT T1.MyColumn,
CHARINDEX('this.text/', T1.myColumn, C.endPos) AS startPos,
CHARINDEX('/', T1.myColumn, CHARINDEX('this.text/', T1.myColumn, c.endPos) + 10) AS endPos
FROM #myTable T1
INNER JOIN CTE C
ON C.myColumn = T1.myColumn
WHERE SUBSTRING(T1.MyColumn, C.EndPos, 100) LIKE '%this.text/%'
)
SELECT DISTINCT SUBSTRING(myColumn, startPos, EndPos - startPos)
FROM CTE
Having a table named test with the following data:
COLUMN1
aathis.text/31/
this.text/1/
bbbthis.text/72/sksk
could this be what you are looking for?
select SUBSTR(COLUMN1,INSTR(COLUMN1,'this.text', 1 ),INSTR(COLUMN1,'/',INSTR(COLUMN1,'this.text', 1 )+10) - INSTR(COLUMN1,'this.text', 1 )+1) from test;
result:
this.text/31/
this.text/1/
this.text/72/
i see your problem:
Assume the same table as above but now with the following data:
this.text/77/
xxthis.text/33/xx
xthis.text/11/xxthis.text/22/x
xthis.text/1/x
The following might help you:
SELECT SUBSTR(COLUMN1, INSTR(COLUMN1,'this.text', 1 ,1), INSTR(COLUMN1,'/',INSTR(COLUMN1,'this.text', 1 ,1)+10) - INSTR(COLUMN1,'this.text', 1 ,1)+1) FROM TEST
UNION
SELECT CASE WHEN (INSTR(COLUMN1,'this.text', 1,2 ) >0) THEN
SUBSTR(COLUMN1, INSTR(COLUMN1,'this.text', 1,2 ), INSTR(COLUMN1,'/',INSTR(COLUMN1,'this.text', 1 ,2),2) - INSTR(COLUMN1,'this.text', 1,2 )+1) end FROM TEST;
it will generate the following result:
this.text/1/
this.text/11/
this.text/22/
this.text/33/
this.text/77/
The downside is that you need to add a select statement for every occurance you might have of "this.text". If you might have 100 "this.text" in the same cell it might be a problem.
SQL> select SUBSTR(column_name,1,9) from tablename;
column_name
this.text
SELECT REGEXP_SUBSTR(column_name,'this.text/[[:digit:]]+/')
FROM table_name