mysql map comma seperated coumn values with new values by table lookup - mysql

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

Related

Week date range

There is a table objects, which stores data on real estate objects. Me need to use a query to calculate a new field that will display the date range from Monday to Sunday, which includes the date the object was created (for example, “2020-11-16 - 2020-11-22”)
create table objects(
object_id int NOT NULL PRIMARY KEY ,
city_id int not null ,
price int ,
area_total int ,
status varchar(50) ,
class varchar(50) ,
action varchar(50) ,
date_create timestamp,
FOREIGN KEY(city_id) references avg_price_square_city(city_id)
);
Data in the table:
INSERT INTO objects (object_id, city_id, price, area_total, status, class, action, date_create)
VALUES (1, 1, 4600000, 72, 'active', 'Secondary', 'Sale', '2022-05-12 21:49:34');
INSERT INTO objects (object_id, city_id, price, area_total, status, class, action, date_create)
VALUES (2, 2, 5400000, 84, 'active', 'Secondary', 'Sale', '2022-05-19 21:49:35');
The query should display two fields: the object number and a range that includes the date it was created. How can this be done ?
P.S
I wrote this query,but he swears at the "-" sign:
SET #WeekRangeStart ='2022/05/10';
SET #WeekRangeEnd = '2022/05/17';
select object_id,#range := #WeekRangeStart '-' #WeekRangeEnd
FROM objects where #range = #WeekRangeStart and date_create between #WeekRangeStart and #WeekRangeEnd
UNION
select object_id,#range from objects where #`range` = #WeekRangeEnd;
Error:[42000][1064] You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '#WeekRangeEnd FROM objects where #range = #WeekRangeStart and date_create betwee' at line 1
I want to receive in query:
object_id #range
1 2022/05/10 - 2022/05/17
The column #range must contain the date from the "date_create"
SET #WeekRangeStart = CAST('2022/05/10' as DATE);
SET #WeekRangeEnd = CAST('2022/05/17' as DATE);
SET #range = CONCAT(#WeekRangeStart,' - ',#WeekRangeEnd) ;
-- select #range;
select
object_id,
#range
FROM objects
where DATE(date_create) between #WeekRangeStart and #WeekRangeEnd
UNION
select object_id,#range from objects
;
Gives next result:
object_id
#range
1
2022-05-10 - 2022-05-17
2
2022-05-10 - 2022-05-17
This result is the output of the SQL part that is put after the UNION. Because date_create is not between your WeekRangeStart and WeekRangeEnd.
You should take some time, and read the UNION documentation.
The variable #range is calculated before the SQL statement, because the value is a constant.
see: DBFIDDLE
NOTE: You should try to use the same dateformat everywhere, and not mix date like '2022-05-19 21:49:35' and 2022/05/10. Use - OR use /, but do not mix them...
EDIT: After the calirification "Me need to use a query to calculate a new field that will display the date range from Monday to Sunday,...":
You probably wanted to do:
SET #WeekDate = CAST('2022/05/10' as DATETIME);
SELECT
ADDDATE(#WeekDate, -(DAYOFWEEK(#WeekDate)-1) +1) as Monday,
DATE_ADD(ADDDATE(#WeekDate, -(DAYOFWEEK(#WeekDate)-1) +9), INTERVAL -1 SECOND) as Sunday;
output:
Monday
Sunday
2022-05-09 00:00:00
2022-05-16 23:59:59

Teradata SQL Split Single String into Table Rows

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
;

Postgres Returning HTML table tags grouped by column for resultset

I'm trying to construct a function that generates the row and cell HTML tags which will be used in another application to build a basic HTML table. The row and cells need to be grouped/concatenated by the region id. This is the part I'm currently struggling with.
I've tried to put the following function together, but not really sure where to go to ensure that the output is grouped correctly by the region_id.
This is not something I would generally do SQL, but I'm working with some limited technologies.
create table reporting
(
id integer,
region_id integer,
category text,
item text,
status text
);
insert into reporting values
(1, 1, 'audio', 'speakers', 'delivered'),
(2, 1, 'display', 'monitors', 'pending'),
(3, 2, 'cables', 'hdmi', 'pre-order'),
(4, 3, 'storage', 'sdd', 'cancelled'),
(5, 3, 'software', 'business', 'delivered'),
(6, 3, 'other', 'support', 'delivered');
create function html_out (query text)
returns TABLE(region_id text, result text) language plpgsql as $$
declare
rec record;
header boolean := true;
begin
for rec in
execute format($q$
select row_to_json(q) json_row
from (%s) q
$q$, query)
loop
return query select region_id,
format ('<tr><td>%s</td></tr>', string_agg(value, '</td><td>'))
from json_each_text(rec.json_row);
end loop;
end $$;
select html_out('select region_id, category, item, status from reporting');
You can use string aggregation. I think the logic you want is:
select
region_id,
'<tr><td>'
|| string_agg(concat_ws('</td><td>', category, item, status), '</td></tr><tr><td>')
|| '</td></tr>' html
from reporting
group by region_id
order by 1
Demo on DB Fiddle
region_id | html
--------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 | <tr><td>audio</td><td>speakers</td><td>delivered</td></tr><tr><td>display</td><td>monitors</td><td>pending</td></tr>
2 | <tr><td>cables</td><td>hdmi</td><td>pre-order</td></tr>
3 | <tr><td>storage</td><td>sdd</td><td>cancelled</td></tr><tr><td>software</td><td>business</td><td>delivered</td></tr><tr><td>other</td><td>support</td><td>delivered</td></tr>
If this is about consolidating repeating region_id with rowspan=, then you can get that in one go like this:
with consolidate as (
select region_id, concat('<td rowspan="', count(*), '">') as rowspan
from reporting
group by region_id
), trows as (
select row_number() over (order by r.region_id, r.id) as rnum,
concat(
'<tr>',
case
when lag(c.region_id) over w = c.region_id then ''
else concat(c.rowspan, c.region_id, '</td>')
end,
'<td>',
array_to_string(array[r.category, r.item, r.status]::text[], '</td><td>', '</td>'),
'</tr>'
) as html
from consolidate c
join reporting r on r.region_id = c.region_id
window w as (partition by r.region_id order by r.id)
)
select array_to_string(array_agg(html order by rnum), '
')
from trows;
-[ RECORD 1 ]---+-----------------------------------------------------------------------------
array_to_string | <tr><td rowspan="2">1</td><td>audio</td><td>speakers</td><td>delivered</tr> +
| <tr><td>display</td><td>monitors</td><td>pending</tr> +
| <tr><td rowspan="1">2</td><td>cables</td><td>hdmi</td><td>pre-order</tr> +
| <tr><td rowspan="3">3</td><td>storage</td><td>sdd</td><td>cancelled</tr> +
| <tr><td>software</td><td>business</td><td>delivered</tr> +
| <tr><td>other</td><td>support</td><td>delivered</tr>
I put a newline in as the delimiter for that last array_to_string() just to get it to look nice. A ' ' or '' would probably be what you want.

Get a value in a single cell into multiple rows using SSRS

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

How to wirte a query for updating two tables at a time?

HI i have two tables in my database named...Requests and Balance tracker which has no relation....but i want to select data from two tables and binf it two grid...
Requests
EmpID |EmpRqsts|EmpDescription|ApproverID|ApprovedAmount|RequestPriority
1 |asdfsb |sadbfsbdf |1 |
2 |asbfd |sjkfbsd |1 |
Balance Tracker
EmpId|BalanceAmnt|LastUpdated|lastApprovedAmount
| 1 |5000 |sdfbk |
| 2 |3000 |sjbfsh |
now i want to update based on the EmpID two tables at a time...when ever amount is approved it should be updates in request table column [ApprovedAmount] and with priority...
when [ApprovedAmount] is Updated [BalanceAmnt] Balance Tracker of also should be Updated by adding the amount approved,[LastUpdated],[lastApprovedAmount] should be updated with date and time
can any one help me with the query please....
#Anil, here is an example of SQL Server 2008 code which would help you to get your goal acomplished:
DECLARE #Requests TABLE
(
EmpId int
, EmpRqsts nvarchar(50)
, EmpDescription nvarchar(250)
, ApproverID int
, ApprovedAmount money
, RequestPriority int
)
DECLARE #BalanceTracker TABLE
(
EmpId int
, BalanceAmnt money
, LastUpdated datetime
, lastApprovedAmount money
)
-- Insert data for testing
INSERT INTO #Requests VALUES
(
1
, 'Something here'
, 'Some descriptio here'
, 1
, 100
, 1
)
INSERT INTO #Requests VALUES
(
2
, 'Something here 2 '
, 'Some descriptio here 3'
, 1
, 215
, 2
)
INSERT INTO #BalanceTracker VALUES
(
1
, 5000
, GETDATE() - 3
, 310
)
INSERT INTO #BalanceTracker VALUES
(
2
, 3000
, (GETDATE() - 1)
, 98
)
-- Declare local variables
DECLARE
#NewAmount money
, #NewPriority int
, #SelectedEmpId int
-- Assing values for example
SELECT #NewAmount = 1000
, #SelectedEmpId = 1
, #NewPriority = 5
-- Get the tables values pre - updates
SELECT *
FROM #Requests
SELECT *
FROM #BalanceTracker
BEGIN TRY
-- Update the record with new ApprovedAmount and Request Priority
UPDATE #Requests
SET ApprovedAmount = #NewAmount
, RequestPriority = #NewPriority
WHERE EmpId = #SelectedEmpId
-- If no error found then update BalanceAmnt trable
IF (##ERROR = 0)
BEGIN TRY
UPDATE #BalanceTracker
SET BalanceAmnt = (BalanceAmnt + #NewAmount)
, LastUpdated = GETDATE()
, lastApprovedAmount = #NewAmount
WHERE EmpId = #SelectedEmpId
END TRY
BEGIN CATCH
PRINT N'Error found updating #BalanceTracker table: ' + ISNULL(LTRIM(STR(ERROR_NUMBER())) , N'Unknown Error' )
+ N', Message: ' + ISNULL ( ERROR_MESSAGE() , N'No Message' )
END CATCH
END TRY
BEGIN CATCH
PRINT N'Error found updating #Requests table: ' + ISNULL(LTRIM(STR(ERROR_NUMBER())) , N'Unknown Error' )
+ N', Message: ' + ISNULL ( ERROR_MESSAGE() , N'No Message' )
END CATCH
-- Get the tables values post - updates
SELECT *
FROM #Requests
SELECT *
FROM #BalanceTracker
Note 1: #Table are Variable Tables handlded by SQL Server 2008. If you're using previous version you should be able to create Temporary Table (#Table).
Note 2: data data-types may vary depending upon the SQL version you're using.
You could do this type of thing with a trigger. This way whenever you do the first update, it will automatically do the other update you specify.