How to add rows to second table from the first table using Common table expression in SQL Server - sql

For example, I have the first table and I want to fill the second table using the first table.
Table A
Name A B C D
-----------------------
name1 a1 b1 c1 d1
name2 a2 b2 c2 d2
Table B (Desired Format)
ID Name Code
----------------------
1 name1 a1
2 name1 b1
3 name1 c1
4 name1 d1
5 name2 a2
6 name2 b2
7 name2 c2
8 name2 d2
As per the suggestions of #Surendra Nath GM, I tried this
DECLARE #counter as int
SET #counter = 1;
;WITH Actual AS
(
SELECT ROW_NUMBER() OVER( ORDER BY IDKEY) as ID FROM Northwind.dbo.Table1
WHERE
),FIRST AS
(
SELECT ((ROW_NUMBER() OVER( ORDER BY IDKEY))*4-3) AS ID,Name, A
FROM Northwind.dbo.Table1
),SECOND AS
(
SELECT ((ROW_NUMBER() OVER( ORDER BY IDKEY))*4-2) AS ID, Name ,B
from Northwind.dbo.Table1
), NEXT AS
(
SELECT ((ROW_NUMBER() OVER( ORDER BY IDKEY))*4-1) AS ID, Name, C
from Northwind.dbo.Table1next
), ________ as
(
SELECT ((ROW_NUMBER() OVER( ORDER BY IDKEY))*4) AS ID, Name, D
from Northwind.dbo.Table1
)
#counter = #counter+1;
)
SELECT * FROM FIRST
UNION ALL
SELECT * FROM SECOND
UNION ALL
SELECT * FROM NEXT
UNION ALL
SELECT * FROM _________
ORDER BY ID
Here, what do I use after the "SECOND AS". I tried writing "THIRD AS" but apparently no such command exists so after some searching, I could write the third row using "NEXT AS" but I am completely clueless as to how do I insert the Fourth row.
I know I can simply write 4 insert commands for each of A,B,C and D but then I will get the not codes in the following order which is NOT desired:
Table B(NOT DESIRED IN THIS FORMAT)
ID Name Code
----------------------
1 name1 a1
2 name2 a2
3 name1 b1
4 name2 b2
5 name1 c1
6 name2 c2
7 name1 d1
8 name2 d2
Also, the desired format can be achieved using simple loops but in the project I am working on, there are around 200000 rows and the simple loops method takes a lot of time. So, I want to do it using CTE. Please help.

You can do it with two inserts:
insert into tableB(A, B)
select A1, B1
from tableA;
insert into tableB(A, B)
select A2, B2
from tableA;
Or union the table with one insert:
insert into tableB(A, B)
select A1, B1
from tableA union all
select A2, B2
from tableA;
This assumes that id is defined as id int indentity(1, 1) so it automatically increments.
If not, you could assign it as:
insert into tableB(id, A, B)
select row_number() over (order by (select NULL)) as id, A1, B1
from (select A1, B1
from tableA union all
select A2, B2
from tableA
) t

getting the ID will be the tricky part over here, in order to do that and use the set opertaions, you have to split the job into two and generate odd ID's for the select of A1,B1 and generate event ID's for the select of A2,B2
Shown as below
;WITH Actual AS
(
SELECT ROW_NUMBER() OVER( ORDER BY Name) as RN, * FROM Table1
),FIRST AS
(
SELECT ((RN*2)-1) AS ID,A1,B1
FROM TABLE1
ORDER BY RN
),SECOND AS
(
SELECT (RN*2) AS ID,A2,B2
FROM TABLE1
ORDER BY RN
)
SELECT * FROM FIRST
UNION ALL
SELECT * FROM SECOND
if you have four columns then you can use the below query instead
;WITH Actual AS
(
SELECT ROW_NUMBER() OVER( ORDER BY Name) as RN, * FROM Table1
),FIRST AS
(
SELECT ((RN*2)-1) AS ID,A1,B1,C1,D1
FROM TABLE1
ORDER BY RN
),SECOND AS
(
SELECT (RN*2) AS ID,A2,B2,C2,D2
FROM TABLE1
ORDER BY RN
)
SELECT * FROM FIRST
UNION ALL
SELECT * FROM SECOND

Related

Case when duplicate add one more letter

For example: I have a table with these records below
1 A
2 A
3 B
4 C
...
and I need to migrate these record in to another table
1 AA
2 AB
3 B
4 C
...
Meaning if the record is duplicate, it will automatically add one more letter alphabetically.
Just a slightly different approach
Example
Declare #YourTable Table (ID int,[SomeCol] varchar(50))
Insert Into #YourTable Values
(1,'A')
,(2,'A')
,(3,'B')
,(4,'C')
Select *
,NewVal = concat(SomeCol,IIF(sum(1) over (partition by SomeCol)=1,'',char(64+row_number() over ( partition by SomeCol order by ID ))) )
From #YourTable
Returns
ID SomeCol NewVal
1 A AA
2 A AB
3 B B
4 C C
EDIT - Requested UPDATE
Declare #YourTable Table (ID int,[SomeCol] varchar(50))
Insert Into #YourTable Values
(1,'A')
,(2,'A')
,(3,'B')
,(4,'C')
Select *
,NewVal = concat(SomeCol,IIF(sum(1) over (partition by SomeCol)=1,'',replace(char(63+row_number() over ( partition by SomeCol order by ID )),'#','')) )
From #YourTable
Returns
ID SomeCol NewVal
1 A A
2 A AA
3 B B
4 C C
We might be able to handle this requirement with the help of a calendar table mapping secondary letters to duplicate sequence counts:
WITH letters AS (
SELECT 1 AS seq, 'A' AS let UNION ALL
SELECT 2, 'B' UNION ALL
SELECT 3, 'C' UNION ALL
...
SELECT 26, 'Z' UNION ALL
...
),
cte AS (
SELECT id, let, ROW_NUMBER() OVER (PARTITION BY let ORDER BY id) rn,
COUNT(*) OVER (PARTITION BY let) cnt
FROM yourTable
)
SELECT t1.id, t1.let + CASE WHEN t1.cnt > 1 THEN t2.let ELSE '' END AS let
FROM cte t1
LEFT JOIN letters t2
ON t1.id = t2.seq
ORDER BY t1.id;
Demo

oracle transposing rows to columns

my question is about transposing rows into columns.
I have got table T1(c1,c2,c3,c4,c5) columns with datatype varchar2, i want to transpose the rows obtained,
example:
select * from T1
gives
c1 c2 c3 c4 c5
row1 1 2 3 4 5
row2 A B C D E
....
rown U V W X Y
the result expected is
C1 1 A......U
C2 2 B......V
C3 3 C......W
C4 4 D......X
C5 5 E......Y
all rows in different columns(table contains only 10-15 rows)
i have tried the following query, but it isnt giving expected result.
Select RN,value
From (
Select x.*,row_number ()
Over ( Order By c1) rn From T1 x)
Unpivot (value For value_type In (C1,c2,c3,c4,c5)
);
So you only need to pivot data again:
dbfiddle demo
select *
from (
select rn, val, col
from (select t1.*, row_number() over (order by c1) rn from t1)
unpivot (val for col in (c1, c2, c3, c4, c5)))
pivot (max(val) for rn in (1, 2, 3, 4))
order by col
You have to know how many rows are in t1 and list them all in pivot in clause (1, 2, 3, 4) alternatively adding aliases for each column.

Complex join in sql with top 10 row

Table1:
Id Word Frequency
1 A 1
2 B 5
Table2:
Id Word SecondWord SecondFrequency
1 A A1 1
2 A A2 5
3 A A3 10
4 A A4 9
5 A A5 20
6 B B1 5
7 B B2 8
8 B B3 50
9 B B4 40
10 B B5 68
Required output
Top 3 record from “Table2” with Order by SecondFrequency Desc
Ex.
Word Frequency SecondWord SecondFrequency
A 1 A5 20
A 1 A3 10
A 1 A4 9
B 5 B5 68
B 5 B3 50
B 5 B4 40
How can i get the desire output
Use ROWNUMBER function based on second frequency for get you required result:
CREATE TABLE #Table1(Id TINYINT, Word VARCHAR(1),Frequency TINYINT)
CREATE TABLE #Table2(Id TINYINT, Word VARCHAR(1),SecondWord
VARCHAR(2),SecondFrequency TINYINT)
INSERT INTO #Table1(Id, Word ,Frequency)
SELECT 1,'A',1 UNION ALL
SELECT 2,'B',5
INSERT INTO #Table2(Id, Word ,SecondWord ,SecondFrequency)
SELECT 1,'A','A1',1 UNION ALL
SELECT 2,'A','A2',5 UNION ALL
SELECT 3,'A','A3',10 UNION ALL
SELECT 4,'A','A4',9 UNION ALL
SELECT 5,'A','A5',20 UNION ALL
SELECT 6,'B','B1',5 UNION ALL
SELECT 7,'B','B2',8 UNION ALL
SELECT 8,'B','B3',50 UNION ALL
SELECT 9,'B','B4',40 UNION ALL
SELECT 10,'B','B5',68
SELECT *
FROM
(
SELECT ROW_NUMBER() OVER(PARTITION BY #Table1.Word ORDER BY
SecondFrequency DESC ) RNo ,#Table1.Word ,#Table1.Frequency,
SecondWord ,SecondFrequency
FROM #Table1
JOIN #Table2 ON #Table1.Word = #Table2.Word
) A
WHERE RNo BETWEEN 1 AND 3
you can use Row Number. By using Row Number you can give each row with the same 'word' a number based on their SecondFrequency. those number will be reset if the 'word' is changed.
;with cte as
(
select *, ROW_NUMBER() OVER (PARTITION BY Word ORDER BY SecondFrequency DESC) AS RowNumber from table2
)
select A.Word, B.Frequency, A.SecondWord, A.SecondFrequency
from cte A left join table1 B
on A.Word = B.Word
where A.RowNumber < 4
Inner Join with Row_Number() will help in this case !!!
CREATE TABLE #Table1
(
Id INT
,Word VARCHAR(10)
,Frequency INT
)
INSERT INTO #Table1 SELECT 1,'A',1
UNION SELECT 2,'B',5
CREATE TABLE #Table2
(
Id INT
,Word VARCHAR(10)
,SecondWord VARCHAR(10)
,SecondFrequency INT
)
INSERT INTO #Table2 SELECT
1,'A','A1',1 UNION ALL SELECT
2,'A','A2',5 UNION ALL SELECT
3,'A','A3',10 UNION ALL SELECT
4,'A','A4',9 UNION ALL SELECT
5,'A','A5',20 UNION ALL SELECT
6,'B','B1',5 UNION ALL SELECT
7,'B','B2',8 UNION ALL SELECT
8,'B','B3',50 UNION ALL SELECT
9,'B','B4',40 UNION ALL SELECT
10,'B','B5',68
SELECT * FROM #Table1
SELECT * FROM #Table2
SELECT X.Word,X.Frequency,X.SecondWord,X.SecondFrequency
FROM
(SELECT T1.Word,T1.Frequency,T2.SecondWord,T2.SecondFrequency,ROW_NUMBER() OVER(PARTITION BY T1.WORD ORDER BY T2.SecondFrequency desc) as RN
FROM #Table1 T1
JOIN #Table2 T2
ON T1.Word = T2.Word
) AS X
WHERE X.RN<=3
get the top 3 rows from Table_2
join the Table_1
the syntax is : ROW_NUMBER() OVER(PARTITION BY COL1 ORDER BY COL2) AS num
COL1 is the column to group and COL2 is the column to sort , num is the sorted number to be used to limit the results
SELECT t2.Word,
t1.Frequency,
t2.SecondWord,
t2.SecondFrequency
FROM
(SELECT *
FROM
(SELECT Word,
SecondWord,
SecondFrequency,
ROW_NUMBER() over(PARTITION BY Word
ORDER BY SecondFrequency DESC) AS num
FROM Table_2) T
WHERE T.num <= 3 ) t2
JOIN Table_1 AS t1 ON t2.Word = t1.Word
ORDER BY t2.SecondFrequency DESC;

SQL Server : join all left table and repeat right

I have to join tables in a following way:
Table A:
1
2
3
4
5
Table B:
A
B
The result table should be:
1 A
2 B
3 A
4 B
5 A
Do you have any ideas how to do this?
Assuming worst case, the column in table A is not a sequence without gaps and the number of rows in table B is not known in advance, you must apply a ROW_NUMBER on both tables and then join on a MODULO:
SELECT col1, col2
FROM
(
SELECT col1,
ROW_NUMBER() OVER (ORDER BY col1) -1 AS rn
FROM tableA
) AS A
JOIN
(
SELECT col2,
ROW_NUMBER() OVER (ORDER BY col2) -1 AS rn
FROM tableB
) AS B
ON A.rn % (SELECT COUNT(*) FROM tableB) = B.rn
Maybe something like this:
select A.nr, case when (A.nr%2=0) then b2.chr else b3.chr end letter
from A, B b2, B b3
where b2.chr = 'A' and b3.chr = 'B'

Select only rows that have unique fields

What is an SQL command that checks for rows that have rows with no duplicate fields in them.
ex:
A A A B B B should not be in the resulting table.
Only rows such as A B C D E F
i.e. given data like:
A A A B B B
A B C D E F
A A B G H Q
Should return A B C D E F
There is no simple command to do this.
is seems an unusual requirement and possibly an indication that the table is not in first normal form if all columns are interchangeable.
The following works in Microsoft SQL Server
;With YourData AS
(
select 'A' as C1, 'A' as C2, 'A' as C3, 'B' as C4, 'B' as C5, 'B' as C6 UNION ALL
select 'A' as C1, 'B' as C2, 'C' as C3, 'D' as C4, 'E' as C5, 'F' as C6
)
SELECT *
FROM YourData
WHERE 1 =
( SELECT TOP 1 COUNT(*) AS Cnt
FROM (
SELECT C1 AS C
UNION ALL
SELECT C2
UNION ALL
SELECT C3
UNION ALL
SELECT C4
UNION ALL
SELECT C5
UNION ALL
SELECT C6
) D
GROUP BY C
ORDER BY Cnt DESC
)
Select distinc * returns unique ROWS not unique values from fields.
You should compare each column's value with others. (Assuming column types are the same). For example, for a 4 column table you should do smoething like:
SELECT Col1, Col2, Col3, Col4 FROM MyTable WHERE
Col1 NOT IN (Col2,Col3,Col4) AND
Col2 NOT IN (Col3,Col4) AND
Col3 <> Col4
SELECT DISTINCT * FROM tablename
SELECT DISTINCT col FROM tabl
SELECT * FROM
mytable
WHERE mytable.col1 != mytable.col2 != mytable.col3 ...