I have few tables, in one of them I am doing load from excel file and then i am doing insert from select
In target table i have column id which doesn't have IDENTITY on it and i cannot create it, so I used ROW_NUMBER() in my select for INSERT,
however now I am having problem, when next time I'm doing load from file into my temp table from which I am selection data for INSERT row number starts from 1 and if iam trying to do insert i am getting error obout problems with Primary key/ So i need to add ID based on id which is already in target table
for example if in target table last record 1000
first record from new Insert has to have id 1001
INSERT INTO table1
( Id ,
OkeiId ,
OkpdId ,
OkvedId ,
)
SELECT
-- (SELECT MAX (id) FROM table1) AS 'last id in table',
ROW_NUMBER() OVER ( ORDER BY ( SELECT 0 ) ) AS Row , -- Id - int
a.[Id] AS OkeId , - int
c.[Id] AS OkpId , - int
D.[Id] AS OkvId , - int
FROM [dbo].#table b
LEFT OUTER JOIN table2 a ON b.F6 = a.[NationalSymbol]
LEFT OUTER JOIN table3 c ON b.F4 = c.Code
LEFT OUTER JOIN table4 D ON b.F5 = D.Code
LEFT OUTER JOIN table1 f ON b.f1 = f.Code
WHERE f.code IS NULL
any Ideas how to continue insert id in sequence? I CANNOT use IDENTITY on this table. I hope you can understand my explanetions
INSERT INTO table1
( Id ,
OkeiId ,
OkpdId ,
OkvedId
)
SELECT
-- (SELECT MAX (id) FROM table1) AS 'last id in table',
a.last_id + ROW_NUMBER() OVER ( ORDER BY ( SELECT 0 ) ) AS Row , -- Id - int
a.[Id] AS OkeiId , -- OkeiId - int
c.[Id] AS OkpdId , -- OkpdId - int
D.[Id] AS OkvedId -- OkvedId - int
FROM [dbo].#table b
LEFT OUTER JOIN table2 a ON b.F6 = a.[NationalSymbol]
LEFT OUTER JOIN table3 c ON b.F4 = c.Code
LEFT OUTER JOIN table4 D ON b.F5 = D.Code
LEFT OUTER JOIN table1 f ON b.f1 = f.Code
CROSS JOIN (SELECT MAX (id) AS last_id FROM table1 ) a
WHERE f.code IS NULL
and some tests:
CREATE TABLE #a
(
a INT PRIMARY KEY,
aa int
)
CREATE TABLE #b
(
b int
)
INSERT INTO #a VALUES(1,1);
INSERT INTO #b VALUES(1);
INSERT INTO #b VALUES(2);
INSERT INTO #b VALUES(3);
INSERT INTO #b VALUES(4);
INSERT INTO #b VALUES(5);
INSERT INTO #a
SELECT last_id + ROW_NUMBER() OVER(ORDER BY b.b), b.b FROM #b b CROSS JOIN (SELECT MAX(a) last_id FROM #a) a
If you're unable to use IDENTITY for some reason and are on SQL Server 2012+, consider sequence numbers. They can be used with multiple columns/tables and are generally more flexible than IDENTITY. See below for examples of creation and use.
Sequence create
CREATE SEQUENCE TestSequence
AS INTEGER
START WITH 1
INCREMENT BY 1;
Sequence use
CREATE TABLE TestTable
(
TestId INTEGER NOT NULL,
TestColumn CHAR(1) NULL
);
INSERT INTO TestTable (TestId, TestColumn)
VALUES (NEXT VALUE FOR TestSequence, 'A');
SQL Fiddle
Related
I have a table 1:
CREATE TABLE table1
INSERT INTO table1 values('XYZ')
INSERT INTO table1 values('ABC')
INSERT INTO table1 values('XYZ~ABC~AAA')
INSERT INTO table1 values('123')
Then, I have string 'ABC~XYZ~123'. I need to split this string into each word by using SQL:
Select VALUE FROM STRING_SPLIT('ABC~XYZ~123','~')
The return is table2
ABC
XYZ
123
I want to count how many times each word in table2 existed in table 1
The expected output is
ABC|3
XYZ|2
123|1
Any ideas on this?
If I understand your case correctly, the next statement may help:
Text and table:
DECLARE #text varchar(100) = 'ABC~XYZ~123'
CREATE TABLE Data (
Id int,
[Text] varchar(100)
)
INSERT INTO Data
(Id, [Text])
VALUES
(1, 'XYZ'),
(2, 'ABC'),
(3, 'XYZ~ABC~AAA'),
(4, '123~ABC')
Statement:
SELECT t.[value] AS [Word], j.[Count]
FROM STRING_SPLIT(#text, '~') t
LEFT JOIN (
SELECT s.[value], COUNT(*) AS [Count]
FROM Data d
CROSS APPLY STRING_SPLIT(d.[Text], '~') s
GROUP BY s.[value]
) j ON t.[value] = j.[value]
Result:
-----------
Word Count
-----------
ABC 3
XYZ 2
123 1
Apart from the suggestions as in comment you can use Count() function as below. But storing in this format will give you difficulty for the extraction as well as in join with the other tables.
Select T1Value, Count(*) as [NoCount] from(
Select table1.Value as T1Value, Value FROM STRING_SPLIT('ABC~XYZ~123','~')
inner join table1 on Value = table1.Value
)a group by T1Value
Edit
CREATE TABLE table1(
TableValue varchar(max)
);
INSERT INTO table1 (TableValue) values ( 'XYZ');
INSERT INTO table1 ( TableValue) values ( 'ABC');
INSERT INTO table1 ( TableValue) values ( 'XYZ~ABC~AAA');
INSERT INTO table1 ( TableValue) values ( '123~ABC');
SELECT b.value
,Count(*)
FROM (
SELECT VALUE
FROM STRING_SPLIT('ABC~XYZ~123', '~')
) a
INNER JOIN (
SELECT *
FROM table1
CROSS APPLY STRING_SPLIT(TableValue, '~')
) b ON a.Value = b.Value
GROUP BY b.Value
Here is the given Live Demo on db <> fiddle
Setup
create table STRINGS (ID int, STRINGS varchar(max));
insert into STRINGS (ID, STRINGS) values (1, 'XYZ');
insert into STRINGS (ID, STRINGS) values (1, 'ABC');
insert into STRINGS (ID, STRINGS) values (1, 'XYZ~ABC~AAA');
insert into STRINGS (ID, STRINGS) values (1, '123~ABC');
declare #VALUES varchar(max) = 'XYZ~ABC~123';
Calculation :
select V1.VALUE, count(STRINGS.ID)
from string_split(#VALUES,'~') V1
cross join STRINGS
outer apply string_split(STRINGS.STRINGS,'~') V2
where V2.VALUE = V1.VALUE
group by V1.VALUE
Result
-----------
Value Num
-----------
ABC 3
XYZ 2
123 1
Live exemple :
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=15b95efcf69ea98fafbb7dda1c624551
I have 2 tables. One is #crecs that stores list of CIDs and a #temp1 that stores clone CVIDs. For the ID in the Crecs table, I want to loop through the #temp1 table to find max(CVID) and pull out the date of the Cloned CVID for that CID based on a condition.
I have boiled down the requirement to below tables:
create table #temp1(cid int,cvid int,flag varchar(5), date1 date, clone int)
insert into #temp1
values ('43','1001','A','1/1/2015',null),
('43','1002','R','2/1/2015',1001),
('43','1003','R','3/1/2015',1002),
('43','1004','R','4/1/2015',1003)
create table #crecs(cid int)
insert into #crecs values(43),(44),(45)
select * from #crecs
select * from #temp1
My query:
select t2.cid,max(t2.cvid),t2.clone,t1.cvid,t1.date1
from #temp1 t2 , #temp1 t1
join #crecs c on c.cid = t1.cid
where t2.clone = t1.cvid
and t1.clone is null and t1.flag = 'A'
group by t2.cid,t2.cvid,t2.clone,t1.cvid,t1.date1
drop table #temp1,#crecs
Desired output:
Below is my rextester link:
http://rextester.com/GSIG28211
Any help?!
You can use a recursive CTE to travel through each clone, then retrieve the last level with MAX() and display it's record.
;WITH RecursiveClones AS
(
SELECT
CID = C.cid,
OriginalCVID = T.cvid,
ClonedCVID = T.cvid,
Level = 0
FROM
#crecs AS C
LEFT JOIN #temp1 AS T ON C.cid = T.cid
WHERE
NOT EXISTS (SELECT 'does not have a clone' FROM #temp1 AS X WHERE X.cvid = T.clone)
UNION ALL
SELECT
CID = R.cid,
OriginalCVID = R.OriginalCVID,
ClonedCVID = T.cvid,
Level = R.Level + 1
FROM
RecursiveClones AS R
INNER JOIN #temp1 AS T ON R.ClonedCVID = T.clone
),
LastCloneByCID AS
(
SELECT
R.CID,
MaxLevel = MAX(R.Level)
FROM
RecursiveClones AS R
GROUP BY
R.CID
)
SELECT
L.CID,
R.ClonedCVID,
R.OriginalCVID,
T.date1
FROM
LastCloneByCID AS L
LEFT JOIN RecursiveClones AS R ON
L.CID = R.CID AND
L.MaxLevel = R.Level
LEFT JOIN #temp1 AS T ON
T.cid = L.CID AND
T.CVID = R.OriginalCVID
I need to add the results from a Left Join query to a table that does not have its index set to be an identity, but the int must still be unique. My insert query looks like this:
INSERT INTO Table1 (S.SubjectID, S.Subject, S.SubjectDescription, S.Status)
SELECT (Select MAX(SubjectID) FROM Table1) + ???? , N.Code, N.Literal, N.Trans
FROM Table2 N LEFT JOIN Table1 S ON N.Code = S.Subject
WHERE (N.Code IS NULL OR S.Subject IS NULL OR N.Trans = 'D')
Where I have the ???? is where i need to have some incrementing value so that when inserting into the table1 the ID's will be unique.
I am not allowed to change the table's structure, I just need something that can calculate his on the fly.
As always help, tips and references are much appreciated.
In most databases, you can use row_number() for this purpose. Here is an example with SQL Server syntax:
INSERT INTO Table1 (S.SubjectID, S.Subject, S.SubjectDescription, S.Status)
SELECT (Select MAX(SubjectID) FROM Table1) + row_number() over (order by (select NULL)) ,
N.Code, N.Literal, N.Trans
FROM Table2 N LEFT JOIN Table1 S ON N.Code = S.Subject
WHERE (N.Code IS NULL OR S.Subject IS NULL OR N.Trans = 'D')
I have tow tables with the same number of rows
Example:
table a:
1,A
2,B
3,C
table b:
AA,BB
AAA,BBB,
AAAA,BBBB
I want a new table made like that in SQL SErver:
1,A,AA,BB
2,B,AAA,BBB
3,C,AAAA,BBBB
How do I do that?
In SQL Server 2005 (or newer), you can use something like this:
-- test data setup
DECLARE #tablea TABLE (ID INT, Val CHAR(1))
INSERT INTO #tablea VALUES(1, 'A'), (2, 'B'), (3, 'C')
DECLARE #tableb TABLE (Val1 VARCHAR(10), Val2 VARCHAR(10))
INSERT INTO #tableb VALUES('AA', 'BB'),('AAA', 'BBB'), ('AAAA', 'BBBB')
-- define CTE for table A - sort by "ID" (I just assumed this - adapt if needed)
;WITH DataFromTableA AS
(
SELECT ID, Val, ROW_NUMBER() OVER(ORDER BY ID) AS RN
FROM #tablea
),
-- define CTE for table B - sort by "Val1" (I just assumed this - adapt if needed)
DataFromTableB AS
(
SELECT Val1, Val2, ROW_NUMBER() OVER(ORDER BY Val1) AS RN
FROM #tableb
)
-- create an INNER JOIN between the two CTE which just basically selected the data
-- from both tables and added a new column "RN" which gets a consecutive number for each row
SELECT
a.ID, a.Val, b.Val1, b.Val2
FROM
DataFromTableA a
INNER JOIN
DataFromTableB b ON a.RN = b.RN
This gives you the requested output:
You could do a rank over the primary keys, then join on that rank:
SELECT RANK() OVER (table1.primaryKey),
T1.*,
T2.*
FROM
SELECT T1.*, T2.*
FROM
(
SELECT RANK() OVER (table1.primaryKey) [rank], table1.* FROM table1
) AS T1
JOIN
(
SELECT RANK() OVER (table2.primaryKey) [rank], table2.* FROM table2
) AS T2 ON T1.[rank] = T2.[rank]
Your query is strange, but in Oracle you can do this:
select a.*, tb.*
from a
, ( select rownum rn, b.* from b ) tb -- temporary b - added rn column
where a.c1 = tb.rn -- assuming first column in a is called c1
if there is not column with numbers in a you can do same trick twice
select ta.*, tb.*
from ( select rownum rn, a.* from a ) ta
, ( select rownum rn, b.* from b ) tb
where ta.rn = tb.rn
Note: be aware that this can generate random combination, for example
1 A AA BB
2 C A B
3 B AAA BBB
because there is no order by in ta and tb
I have a database with two tables (Table1 and Table2). Table1 has one column ColumnA and Table2 has one column ColumnB i want to select both the columns,
looking for something like:
ColumnA in Table1:
a
b
c
ColumnA in Table2:
d
e
f
Result set should be:
a d
b e
c f
Thanks in advance..
I am pretty sure sql server 2000 supports table vars so you can try this
DECLARE #TableA TABLE(
ID INT IDENTITY(1,1),
Val VARCHAR(50)
)
INSERT INTO #TableA (Val) SELECT ColumnA FROM Table1
DECLARE #TableB TABLE(
ID INT IDENTITY(1,1),
Val VARCHAR(50)
)
INSERT INTO #TableB (Val) SELECT ColumnB FROM Table2
SELECT a.Val,
b.Val
FROM #TableA a INNER JOIN
#TableB b ON a.ID = b.ID
Since you have no relation between the two tables, this operation is not really defined. What row in table1 goes with what row in table2?
You should set up a relation.
What is it you want to achieve anyway?
I don't know the big picture but from what you've said, here's an example. There has to be some way to define which record in table 1 should match up with a record in table 2. I'm assuming they match up on the ordering when ordered by the column in each table (e.g. record 1 from Table 1 ordered by column A, matches with record 1 from Table 2 ordered by column B). This example requires SQL 2005 or higher.
DECLARE #T1 TABLE (A varchar(10))
DECLARE #T2 TABLE (B varchar(10))
INSERT #T1 VALUES ('a')
INSERT #T1 VALUES ('b')
INSERT #T1 VALUES ('c')
INSERT #T2 VALUES ('d')
INSERT #T2 VALUES ('e')
INSERT #T2 VALUES ('f')
SELECT A, B
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY A ASC) AS RowNo, A
FROM #T1
) t1
JOIN
(
SELECT ROW_NUMBER() OVER (ORDER BY B ASC) AS RowNo, B
FROM #T2
) t2 ON t1.RowNo = t2.RowNo
How will the system know to associate the 'a' value from table1 with the 'd' value from table 2? If someone adds another row to table2 with value 'c' should your query now output
null- c
a - d
b - e
c - f
or
a - c
b - d
c - e
or
a - c
b - d
c - e
null- f
??? --- You have to specify in some way what rules to use to associate the rows from table1 with the rows from table2.
If you just want the rows associated based on alphabetical sorting,
then if the values are unique in each of the tables, (using standard SQL only), try this
Select Z1.ColumnA, z2.ColumnB
From (Select ColumnA,
(Select Count(*)
From Table1
Where ColumnA < t1.ColumnA) RowNo,
From Table1 T1) z1
Join (Select ColumnB,
(Select Count(*)
From Table2
Where ColumnB < t2.ColumnB) RowNo,
From Table2 T2) z2
On z1.RowNo = z2.RowNo
Order By z1.RowNo