I currently have only one column in a table. Each row contains the exact same amount of characters. I need a way to be able to split this one column into multiple columns. The table has over 1.1 million rows, so efficiency in code is pretty important. All of the rows are set up with the same structure, meaning the first 5 characters are always dedicated for firstname, the next 6 are always for lastname for example. I know how to take the left most characters using:
insert into table2
select left(column1,2), substring(column1, 3, len(column1) ) from table1
The problem with the above, is that 1) it creates a new table instead of modifying the existing. And 2) Once I have the first set of characters split into a column I don't know how to grab the next set.
Below is an example of how I would like it to work:
Current
Column 1
abcdefghijklmnop
qrstuvwxyz123456
What I would like:
Column 1 ----------- Column 2 --------- Column 3
abcdefg--------------hij----------------klmnop
qrstuvw--------------xyz----------------123456
picture below:
I can usually fix this through how I important the data in SQL. However the txt file that I use to import the data has no way to dilimate the columns correctly so it has to all be brought in as one column.
Here is the exact scenario that you have mentioned here.
DROP TABLE dbo.table1
DROP TABLE dbo.table2
CREATE TABLE dbo.table1
(column1 VARCHAR(100))
CREATE TABLE dbo.table2
(column1 VARCHAR(100),
column2 VARCHAR(100),
column3 VARCHAR(100)
)
INSERT INTO dbo.table1
VALUES ('abcdefghijklmnop'),('qrstuvwxyz123456')
INSERT INTO dbo.table2
SELECT LEFT(column1,7) AS column1,SUBSTRING(column1,8,3) column2,RIGHT(column1,6) column3
FROM dbo.table1
SELECT *
FROM table1
SELECT *
FROM table2
this should help
select 'dgfsrsdgsdghshdsdfhzhs' column1 into #table_name
ALTER TABLE #table_name
ADD firstname varchar(5) ,
lastname varchar(6);
update #table_name
set firstname = SUBSTRING (column1,1,5),
lastname = SUBSTRING (column1,6,6)
select * from #table_name
assuming that the modification has to be done in the same table and SUBSTRING startposition and length are taken according the output that is being expected below code will do the needful
UPDATE table1
SET column1=SUBSTRING(c1,1,8),
column2=SUBSTRING(c1,8,3),
column3=SUBSTRING(c1,11,7)
Related
I currently import a file dynamically using SSIS into a SQL table, part of the process imports the column headers from the source file into the first row of a table (table 1 below).
I then want to compare the headers from table 1 with table 2 which has static columns, and most importantly highlight any column headers from table 1 that do not exist in table 2.
So for example Table 1 looks like this:
Column 1
Column 2
CustomerID
CustomerName
And table 2 has static column headers like the following:
CustomerID
CustomerName
1
Joe
2
Daniel
So basically when I load a file and a new column header is added (in this example lets say CustomerLocation is added) and loaded into table 1, I want a SQL query to compare the 2 tables and highlight that the column CustomerLocation is missing/does not exist in table 2 currently.
I was thinking along the lines of using the sys tables to compare.
You certainly could use sys.columns to return your static columns from Table2 and compare them to the dynamic columns in Table1 and use UNPIVOT on a select of your first row.
I have found that it was far easier to wrap this all in a T-SQL block and insert to two lists into temp tables before comparing due to data type conflicts (probably be solved by using CAST)
BEGIN
DECLARE #table1 TABLE (colname VARCHAR(MAX))
DECLARE #table2 TABLE (colname VARCHAR(MAX))
INSERT INTO #table1 SELECT COLNAME FROM (SELECT a, b, c FROM TABLE1 WHERE...first row condition) a UNPIVOT (COLNAME FOR COLS IN ([a],[b],[c])) a
INSERT INTO #table2 SELECT CAST (name AS NVARCHAR(100)) name FROM sys.columns WHERE object_id = OBJECT_ID('TABLE2')
SELECT a.colname cols1, b.colname cols2
FROM #table2 a
FULL OUTER JOIN #table1 b ON (a.colname = b.colname)
END
You can easily change the final select to return what you want
Hi I have following records in database:- Table1
Basically i want those records from Table1 that only Asserted but not Cleared from Alert column I have highlighted in Table1.
If you see in Alert column HD of Record20,C2 of Record14 and L1 of Record21 columns are only ASSERTED But not CLEARED.
Show i want to show those records from Alert column which ASSERTED but not CLEARED using sql server.
I think this is what you want:
select t1.*
from t t1
where alerts like '%Asserted%' and
not exists (select 1
from t t2
where t2.alerts like '%Cleared%' and
t2.alerts like left(t1.alerts, charindex(' ', t1.alerts)) + '%'
);
You should really fix the data model so the entity with the alarm is in a separate column.
Try this:
Select * from tbl where replace(Alerts, 'Asserted','') in
(
Select replace(Alerts, 'Asserted', '') a from tbl
where Alerts like '%Asserted%'
except
select replace(Alerts, 'Cleared','') a from tbl
where Alerts like '%Cleared%'
)
Try this WHERE condition to test that column
SELECT Alerts
FROM Table1
WHERE
Alerts LIKE '%Asserted%'
AND
Alerts NOT LIKE '%Cleared%';
Modify the first row to include whatever other columns you want, as I only for simplicity and readability used to show only the column which will be tested against conditions.
You can try the following query.
create table tblRecord (record varchar(10), tempText Varchar(20))
insert into tblRecord values
('record1', 'a1 asserted'),('record1', 'a1 cleared'),('record2', 'a2 asserted'),('record2', 'a2 cleared'),('record3', 'a3 asserted')
Select * from tblRecord where tempText like '%asserted%' --To get the records with asserted values
and record not in --To remove the records with cleared values
(
select record from tblRecord
where REVERSE(LEFT(REVERSE(tempText), CHARINDEX(' ',REVERSE(tempText))- 1)) = 'cleared' --Last word
)
Live Demo
I need to be able to write a SQL to match customerid where the # of characters differs between tables. As you will see below, table 1 has the CustomerId with no padding (# of characters may differ, as shown within the example). Table 2 has a specific format of '0001' + 0 padding to make the field a total of 30 characters.
So, if I needed to write SQL for this, for table1 CustomerIds, would this be some type of substring?
Example:.
Table1 has customerid as '123456'.
Table 2 has customerid as '000100000000000000000000123456'
Example 2:
Table 1 has customerid as '98765432'
Table 2 has customerid as '000100000000000000000099765432'
You should pad the value from the table1 with 0001 and zeroes until it is 30 characters and then use that to compare.
where '0001'||lpad(columnname,'0',26) = columnname2
........
where table2.customerID like '%' || table1.customerID
like is really a misnomer, it means "equals". '%' will match an arbitrary string, of any length (zero or more).
LIKE should definitely a good option.
One more way, assuming that the columns contain only numeric characters, you could use:-
ON ( TO_NUMBER(SUBSTR(tab2.customerid,5)) = tab1.customerid )
Adding a function based INDEX on TO_NUMBER(SUBSTR(tab1.customerid,5) may speed up the query.
you can also use ltrim function for it like query below just trimming off 0s or 1s from table2's customerid:
select * from ns_table2 a,ns_table3 b where
ltrim(b.val1,'01')=ltrim(a.val1,'01') ;
sample input:
create table ns_table2(val1 varchar(30),val2 varchar(30));
create table ns_table3(val1 varchar(30),val2 varchar(30));
insert into ns_table2 values('123456','table2');
insert into ns_table2 values('98765432','table2');
insert into ns_table3 values('000100000000000000000000123456','table3');
insert into ns_table3 values('000100000000000000000098765432','table3');
select * from ns_table2 a,ns_table3 b where
ltrim(b.val1,'01')=ltrim(a.val1,'01') ;
sample output:
123456 table2 000100000000000000000000123456 table3
98765432 table2 000100000000000000000098765432 table3
I am having a table which is having a column named as CDR.
In that CDR column we have values stored as comma separated like 20,5,40,10,30
I just need to replace last value(here it is 30) to 0 in every row.
Can someone suggest me how can we do?
Thanks
If you are able, first correct the database design as the table is not in first normal form. It is bad design to have more than one value stored in one column, as evidenced by you having to ask this question. :-) Having said that, I have to deal with vendor data that has the same issue that is beyond my control to change, so in Oracle 11g I would do this:
update table_name
set CDR = regexp_replace(CDR, '(.*,)\d+$', '\10');
The regex matches and remembers all characters up to and including the last comma before one or more digits right before the end of the string. The replace string is the remembered part referenced by the \1, referring to the first grouping of characters inside parenthesis), plus the 0.
If you are using SQL Server, this should do for you.
create table #A(id int , cdr varchar(100))
insert into #A values(1,'10,20,30,40'),(2, '20,30,40,50'),(3,'30,40,50,60,70')
Declare #tA as table(id int , String varchar(10))
insert into #tA
SELECT id,
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT [id],
CAST ('<M>' + REPLACE([cdr], ',', '</M><M>') + '</M>' AS XML) AS String
FROM #A) AS A CROSS APPLY String.nodes ('/M') AS Split(a);
delete from #tA where [String] = '30'
SELECT distinct id,
ISNULL(STUFF((SELECT ', ' + String
FROM #tA t
WHERE t.id = ta.id
FOR XML PATH('')
), 1, 1, ''), '') AS Str
into #tempA
FROM #tA ta
select * from #tempA
drop table #A, #tempA
UPDATE TableName
SET CDR = REPLACE(CDR, (SUBSTRING( CDR, LEN(CDR) - CHARINDEX(',',REVERSE(CDR)) + 2 , LEN(CDR))),0);
You should think about splitting up your comma separated list into a separate table. That way you can do other things in SQL. SQL is not the best with string manipulation and your queries are gonna get obscene and unruly.
table Users
user_id user_name job_list
1 Billy "1,2,3,4"
table Jobs
job_id job_desc
1 plumber
2 carpenter
3 electrician
4 programmer
If you do this you're gonna have some heartaches where a job goes away or something you're gonna have a lot of annoying cleanup like #jarlh suggests.
If you make a third table to hold the relationships user_id to job_id you will have a much better time if you need to do something like delete a job_id from existence. Of course this is all made up based on your limited question, but it should help you out.
table UserJobRelationship
relationship_id user_id job_id
1 1 1
2 1 2
3 1 3
4 1 4
Gives you much more flexibility and allows you to delete the most recent entry. You can simply just do max of relationship_id where user_id equals that user or you can do it for the whole table.
Hi all I was just curious if I could do something like -
insert into Employee ( Select * from Employee where EmployeeId=1)
I just felt the need to do this a lot of times...so just was curious if there was any way to achieve it..
You can do something like that, but you cannot Select * if you want to change a column value:
Insert into employee ( employeeId, someColumn, someOtherColumn )
Select 2, someColumn, someOtherColumn
From employee
Where employeeId=1
This would insert 2 as your new employeeId.
yes list out the column and do it like that
insert into Employee (EmployeeId, LastName, FirstName......)
Select 600 as EmployeeId, LastName, FirstName......
from Employee where EmployeeId=1
However if EmployeeId is an identity column then you also need to do
set identity_insert employee on
first and then
set identity_insert employee off
after you are done
You could use the INSERT INTO ... SELECT ... syntax if the destination table already exists, and you just want to append rows to it. It's easy to check if you are selecting your data by executing just the SELECT part.
Insert into existingTable ( Column1, Column2, Column3, ... )
Select 1, Column2, Column3
From tableName
Where ....
You are not restricted to a simple select, the SELECT statement can be as complex as necessary. Also you do not need to provide names for the selected columns, as they will be provided by the destination table.
However, if you have autoincrement columns on the dest table, you can either omit them from the INSERT's column list or use the 'set identity_insert' configuration.
If you want to create a new table from existing data, then you should use the SELECT ... INTO ... syntax
Select 1 as Column1, Column2, Column3
Into newTable
From tableName
Where ....
Again, the select can be arbitrarily complex, but, because the column names are taken from the select statement, all columns must have explicit names. This syntax will give an error if the 'newTable' table already exists. This form is very convenient if you want to make a quick copy of a table to try something.