How to split data in SQL Server table row - sql

I have table of transaction which contains a column transactionId that has values like |H000021|B1|.
I need to make a join with table Category which has a column CategoryID with values like H000021.
I cannot apply join unless data is same.
So I want to split or remove the unnecessary data contained in TransctionId so that I can join both tables.
Kindly help me with the solutions.

Create a computed column with the code only.
Initial scenario:
create table Transactions
(
transactionId varchar(12) primary key,
whatever varchar(100)
)
create table Category
(
transactionId varchar(7) primary key,
name varchar(100)
)
insert into Transactions
select'|H000021|B1|', 'Anything'
insert into Category
select 'H000021', 'A category'
Add computed column:
alter table Transactions add transactionId_code as substring(transactionid, 2, 7) persisted
Join using the new computed column:
select *
from Transactions t
inner join Category c on t.transactionId_code = c.transactionId
Get a straighforward query plan:

You should fix your data so the columns are the same. But sometimes we are stuck with other people's bad design decisions. In particular, the transaction data should contain a column for the category -- even if the category is part of the id.
In any case:
select . . .
from transaction t join
category c
on transactionid like '|' + categoryid + |%';
Or if the category id is always 7 characters:
select . . .
from transaction t join
category c
on categoryid = substring(transactionid, 2, 7)

You can do this using query :
CREATE TABLE #MyTable
(PrimaryKey int PRIMARY KEY,
KeyTransacFull varchar(50)
);
GO
CREATE TABLE #MyTransaction
(PrimaryKey int PRIMARY KEY,
KeyTransac varchar(50)
);
GO
INSERT INTO #MyTable
SELECT 1, '|H000021|B1|'
INSERT INTO #MyTable
SELECT 2, '|H000021|B1|'
INSERT INTO #MyTransaction
SELECT 1, 'H000021'
SELECT * FROM #MyTable
SELECT * FROM #MyTransaction
SELECT *
FROM #MyTable
JOIN #MyTransaction ON KeyTransacFull LIKE '|'+KeyTransac+'|%'
DROP TABLE #MyTable
DROP TABLE #MyTransaction

Related

Dynamically created Tables JOIN in SQL Server

I have 3 types of tables
Major table as follows
CREATE TABLE #InitialTable
(
Id int PRIMARY KEY IDENTITY(1,1),
RP varchar(20)
)
INSERT INTO #InitialTable
VALUES ('R1', 'R2', 'R3')
GO
Table contains dynamically created tables information as follows
CREATE TABLE #DynamicTablesInfo
(
Id int PRIMARY KEY IDENTITY(1,1),
RPId int FOREIGN KEY REFERENCES #InitialTable(Id),
TableName varchar(100)
)
GO
INSERT INTO #DynamicTablesInfo
VALUES (1, 'Table_X1'), (2, 'Table_X2'), (3, 'Table_X3')
GO
Dynamically created tables these tables can be any number of tables and the tables info is available in above table.
CREATE TABLE #Table_X1
(
Id int PRIMARY KEY IDENTITY,
Version_Value varchar(100)
)
GO
INSERT INTO #Table_X1
VALUES ('Val_X1_1'), ('Val_X1_2'), ('Val_X1_3')
GO
CREATE TABLE #Table_X2
(
Id int PRIMARY KEY IDENTITY,
Version_Value varchar(100)
)
GO
INSERT INTO #Table_X2
VALUES ('Val_X2_1'), ('Val_X2_2'), ('Val_X2_3')
GO
CREATE TABLE #Table_X3
(
Id int PRIMARY KEY IDENTITY,
Version_Value varchar(100)
)
GO
INSERT INTO #Table_X3
VALUES ('Val_X3_1'), ('Val_X3_2'), ('Val_X3_3')
GO
Now I wanted to join InitialTable with dynamically created tables (Table_X1, Table_X2, Table_X3,....) with the help of DynamicTablesInfo table - how to do that?
Note: for easy update, delete, insert I created them as temporary tables but in my application all are real tables.
Instead of doing this:
CREATE TABLE #Table_X1
(
Id int PRIMARY KEY IDENTITY
,Version_Value varchar(100)
)
GO
CREATE TABLE #Table_X2
(
Id int PRIMARY KEY IDENTITY
,Version_Value varchar(100)
)
GO
CREATE TABLE #Table_X3
(
Id int PRIMARY KEY IDENTITY
,Version_Value varchar(100)
)
GO
Do this one time:
CREATE TABLE Table_X
(
Id int PRIMARY KEY IDENTITY
,Version_Value varchar(100)
,X_number INT
)
GO
Then instead of doing this:
INSERT INTO #Table_X1 VALUES ('Val_X1_1'),('Val_X1_2'),('Val_X1_3')
INSERT INTO #Table_X2 VALUES ('Val_X2_1'),('Val_X2_2'),('Val_X2_3')
INSERT INTO #Table_X3 VALUES ('Val_X3_1'),('Val_X3_2'),('Val_X3_3')
Do this:
INSERT INTO Table_X VALUES ('Val_X1_1',1),('Val_X1_2',1),('Val_X1_3',1)
INSERT INTO Table_X VALUES ('Val_X2_1',2),('Val_X2_2',2),('Val_X2_3',2)
INSERT INTO Table_X VALUES ('Val_X3_1',3),('Val_X3_2',3),('Val_X3_3',3)
Much easier to query without dynamics:
--no
SELECT * FROM Table_X1
--yes
SELECY * FROM Table_X WHERE X_Number = 1
You've indicated you're stuck with it how it is, so you'll need to create and run your queries dynamically too. This is c#/vb flavored pseudocode:
string sql = "SELECT * FROM sometable"
for int x = 1 to 3
sql = sql + " table_x{x} on sometable.id = table_x{x}.id"
Or perhaps build a Union:
string sql = "WITH allx AS (SELECT * FROM table_x1"
for int x = 2 to 10
sql = sql + " UNION ALL SELECT * FROM table_x{x}"
sql = sql + ") select * from sometable inner join allx on..."
But I echo larnu's sentiments in the comments.. if you truly cannot change the tables that are created, consider creating a VIEW in a similar way to the UNION code above, that will sit alongside X number of tables and will provide a way to query without dynamic:
CREATE VIEW AllX AS(
SELECT x.*, 1 as Which FROM TABLE_X1 x
UNION ALL SELECT x.*, 2 as Which FROM TABLE_X2 x
UNION ALL SELECT x.*, 3 as Which FROM TABLE_X3 x
...
Use the same technique that creates 10 tables to string together a CREATE VIEW statement that views over the 10 tables, then you can query the view without Dynamic sql generation

sql temp table and while?

I have a table (for example) with products and second with descriptions of these products.
I've created in procedure with one temp table which contains all ID of products that are NOT in table with description. Now I want to add these all descriptions for Ids from temp table. How can I achieve this? Loop cant be I think cause it will never end.
Please help ;)
I cannot use a trigger, and I'm using SQL Server 2016.
IF OBJECT_ID('tempdb.dbo.#Pr') IS NOT NULL
DROP TABLE #Pr;
CREATE TABLE #Pr
(
[Id] int
);
INSERT INTO #Pr
SELECT
[Id]
FROM
[db].[Products]
IF OBJECT_ID('tempdb.dbo.#Pr2') IS NOT NULL
DROP TABLE #Pr2;
CREATE TABLE #Pr2
(
[Id] int
);
INSERT INTO #Pr2
SELECT
[Id]
FROM
#Pr p1
WHERE
NOT EXISTS (SELECT [Id]
FROM [db].[Descriptions] p2
WHERE p1.[Id] = p2.[Id])
IF EXISTS (SELECT NULL FROM #Pr2)
You seem to want insert with a check that something is not already in the table. NOT EXISTS can be used for this purpose:
insert into products (product, description)
select product, description
from temp_products tp
where not exists (select 1 from products p where p.product = tp.product);

Data Definition Language (DDL) Query SQL

I'm new in query and SQL server, and I wanted to know about DDL.
I have an attribute in my Table which has more than 1 value, such as
Size = {'S', 'M', 'L'}.
How could i make the attribute in my Table with query, so i can insert multi values to one of my attribute?
You don't want to do this, because this is denormalizing your data. But, if you must.
declare #table table (id int identity(1,1), size varchar(16))
insert into #table
values
('S')
,('M')
select * from #table
update #table
set size = size + ',M'
where id = 1
select * from #table
Here is a one to many approach with a foreign key
create table #items (id int identity(1,1), descrip varchar(64))
insert into #items
values
('shirt'),
('pants')
create table #item_sizes (id int identity(1,1), size char(1), item_id int)
alter table #item_sizes
add constraint FK_item foreign key (item_id) references #items(id)
insert into #item_sizes
values
('S',1)
,('M',1)
,('L',1)
,('S',2)
select
ItemID = i.id
,i.descrip
,isiz.size
from #items i
inner join #item_sizes isiz
on isiz.item_id = i.id
drop table #items, #item_sizes
As per your requirement :
Product (...,ProductSize);
INSERT INTO Product (ProductSize) VALUES ('S')
How to query the row of ProductSize so i can insert more than one values in SQL? –
you can query like below
select * from Product where ProductSize like '%S%' or ProductSize like '%L%' or ProductSize like '%M%'

Is it possible to create indexes on a temp table when using SELECT INTO?

I am loading data from a CSV file into a temp staging table and this temp table is being queried a lot. I looked at my execution plan and saw that a lot of the time is spent scanning the temp table.
Is there any way to create index on this table when I SELECT INTO it?
SELECT *
FROM TradeTable.staging.Security s
WHERE (
s.Identifier IS NOT NULL
OR s.ConstituentTicker IS NOT NULL
OR s.CompositeTicker IS NOT NULL
OR s.CUSIP IS NOT NULL
OR s.ISIN IS NOT NULL
OR s.SEDOL IS NOT NULL
OR s.eSignalTicker IS NOT NULL)
The table created by SELECT INTO is always a heap. If you want a PK/Identity column you can either do as you suggest in the comments
CREATE TABLE #T
(
Id INT IDENTITY(1,1) PRIMARY KEY,
/*Other Columns*/
)
INSERT INTO #T
SELECT *
FROM TradeTable.staging.Security
Or avoid the explicit CREATE and need to list all columns out with
SELECT TOP (0) IDENTITY(int,1,1) As Id, *
INTO #T
FROM TradeTable.staging.Security
ALTER TABLE #T ADD PRIMARY KEY(Id)
INSERT INTO #T
SELECT *
FROM TradeTable.staging.Security

insert data into several tables

Let us say I have a table (everything is very much simplified):
create table OriginalData (
ItemName NVARCHAR(255) not null
)
And I would like to insert its data (set based!) into two tables which model inheritance
create table Statements (
Id int IDENTITY NOT NULL,
ProposalDateTime DATETIME null
)
create table Items (
StatementFk INT not null,
ItemName NVARCHAR(255) null,
primary key (StatementFk)
)
Statements is the parent table and Items is the child table. I have no problem doing this with one row which involves the use of IDENT_CURRENT but I have no idea how to do this set based (i.e. enter several rows into both tables).
Thanks.
Best wishes,
Christian
Another possible method that would prevent the use of cursors, which is generally not a best practice for SQL, is listed below... It uses the OUTPUT clause to capture the insert results from the one table to be used in the insert to the second table.
Note this example makes one assumption in the fact that I moved your IDENTITY column to the Items table. I believe that would be acceptable, atleast based on your original table layout, since the primary key of that table is the StatementFK column.
Note this example code was tested via SQL 2005...
IF OBJECT_ID('tempdb..#OriginalData') IS NOT NULL
DROP TABLE #OriginalData
IF OBJECT_ID('tempdb..#Statements') IS NOT NULL
DROP TABLE #Statements
IF OBJECT_ID('tempdb..#Items') IS NOT NULL
DROP TABLE #Items
create table #OriginalData
( ItemName NVARCHAR(255) not null )
create table #Statements
( Id int NOT NULL,
ProposalDateTime DATETIME null )
create table #Items
( StatementFk INT IDENTITY not null,
ItemName NVARCHAR(255) null,
primary key (StatementFk) )
INSERT INTO #OriginalData
( ItemName )
SELECT 'Shirt'
UNION ALL SELECT 'Pants'
UNION ALL SELECT 'Socks'
UNION ALL SELECT 'Shoes'
UNION ALL SELECT 'Hat'
DECLARE #myTableVar table
( StatementFk int,
ItemName nvarchar(255) )
INSERT INTO #Items
( ItemName )
OUTPUT INSERTED.StatementFk, INSERTED.ItemName
INTO #myTableVar
SELECT ItemName
FROM #OriginalData
INSERT INTO #Statements
( ID, ProposalDateTime )
SELECT
StatementFK, getdate()
FROM #myTableVar
You will need to write an ETL process to do this. You may want to look into SSIS.
This also can be done with t-sql and possibly temp tables. You may need to store unique key from OriginalTable in Statements table and then when you are inserting Items - join OriginalTable with Statements on that unique key to get the ID.
I don't think you could do it in one chunk but you could certainly do it with a cursor loop
DECLARE #bla char(10)
DECLARE #ID int
DECLARE c1 CURSOR
FOR
SELECT bla
FROM OriginalData
OPEN c1
FETCH NEXT FROM c1
INTO #bla
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO Statements(ProposalDateTime) VALUES('SomeDate')
SET #ID = SCOPE_IDENTITY()
INSERT INTO Items(StateMentFK,ItemNAme) VALUES(#ID,#bla)
FETCH NEXT FROM c1
INTO #bla
END
CLOSE c1
DEALLOCATE c1