TSQL merge 2 dataset with even number of rows next to eachother - sql

What I am trying to accomplish:
Dataset 1
Name1
Name2
Name3
Dataset 2
Number1
Number2
Number3
will become 2 columns:
dataset1 dataset2
Name1 Number1
Name2 Number2
Name3 Number3
My datasets 1 & 2 will always have equal rows.
Which name linked to which number I don't care as long as two names are not linked to the same number and vice versa.
How can I solve this with SQL / SQL Server ?

If you don't want to add an identity column to the tables, you can use the ROW_NUMBER() function like this:
SELECT
T1.Col1,
T2.Col1
FROM
(SELECT Col1, ROW_NUMBER() OVER (ORDER BY Col1) AS N FROM Table1) T1
INNER JOIN
(SELECT Col1, ROW_NUMBER() OVER (ORDER BY Col1) AS N FROM Table2) T2
ON T1.N = T2.N
Here, replace Table1 and Table2 with the name of your tables, and replace Col1 with the name of the column (or columns) that you want to output from the two tables.

Add identity columns to both the tables and perform join on basis of these column
ALTER TABLE Table1
ADD ID INT IDENTITY(1,1) NOT NULL
ALTER TABLE Table2
ADD ID INT IDENTITY(1,1) NOT NULL
SELECT Table1.dataset1col , Table2.dataset2Col
From Table1 INNER JOIN Table2
ON Table1.ID = Table2.ID

This may work for you :
;WITH cte1 (name, rn)
AS (SELECT Name,
row_number()
OVER(
ORDER BY Name) rn
FROM Dataset1),
cte2 (Number, rn)
AS (SELECT Number,
row_number()
OVER(
ORDER BY Number) rn
FROM Dataset2)
SELECT name,
Number
FROM cte1
JOIN cte2
ON cte1.rn = cte2.rn

WITH Table1 AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Dataset1) as Rnk,Dataset1
FROM TA1
)
With Table2 AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Dataset2) as Rnk, Dataset2
FROM TA2
)
Select Table.Dataset1 as 'DataSet1', Table2.DataSet2 as 'DataSet2'
From Table1
inner join Table2 on Table1.Rnk = Table2.Rnk
Because you haven't added table name so I considered it as TA1 and TA2.

Another way of writing the query is:
select row_number() over (order by Names asc) as rownum,
Names
into #Temp1
from NameTable
select row_number() over (order by Numbers asc) as rownum,
Numbers
into #Temp2
from NumberTable
select Names, Numbers
from #Temp1
inner join #Temp2 on #Temp1.rownum = #Temp2.rownum
Demo

There are 3 possible solutions to this.
First: Use following trick (Warning: Use this in case of small datasets)
SELECT DISTINCT tbl1.col1, tbl2.col2
FROM
(SELECT FirstName AS col1, ROW_NUMBER() OVER (ORDER BY FirstName) Number FROM dbo.User) tbl1
INNER JOIN
(SELECT LastName AS col2, ROW_NUMBER() OVER (ORDER BY LastName) Number FROM dbo.User) tbl2
ON tbl1.Number = tbl2.Number
Second: Use variable tables to store result temporarily. This solution is for relatively large datasets. (approx records to 100s)
Third:
Use identitfy field in both tables as already mentioned by mmhasannn. But i will prefer this method least, as we need to modify our DB structure.
RECOMMENDED: Use variable tables approach

Related

Showing two temp tables data in a single table

I have one temp table having data like below in sql server
Table 1
**Data**
ISD-I987330
PSD-I987330
KSD-I987330
JSD-I987330
RSD-I987330
QSD-I987330
QSD-I987359
And another temp table having data like below
Table 2
**Data**
BRA-22310
BRA-22319
BRA-22316
BRA-22313
BRA-22317
I am trying to display both these tables data in a single table.Like below
But I am getting cross joins data.
Below is my query
declare #TempResults table
(
Tickets1 varchar(50),
Tickets2 varchar(50)
)
insert into #TempResults
Select distinct ti.Tickets1,
tr.Tickets2
FROM #Table1 ti,#table2 tr
select * from #TempResults
You can't really get the output you want without each table having a separate column which maintains the order of each record, in each table. Absent that, we could use ROW_NUMBER to generate an order, and then join:
WITH cte1 AS (
SELECT Data, ROW_NUMBER() OVER (ORDER BY Data) rn
FROM Table1
),
cte2 AS (
SELECT Data, ROW_NUMBER() OVER (ORDER BY Data) rn
FROM Table2
)
SELECT
t1.Data,
t2.Data
FROM cte1 t1
FULL OUTER JOIN cte2 t2
ON t1.rn = t2.rn;
you can join using row_number()
with cte1 as
(select *,row_number() over(order by data) rn
from table1
),
cte2 as
(
select *,row_number() over(order by data) rn
) select cte1.data,cte2.data from cte1 left join ct2 on cte1.rn=cte2.rn
The most basic solution but not necessarily the best, is to make the union of tables in a temporary table with different names for each of the columns
select * Into #TempResults From
(
SELECT ti.Tickets1 as 'Tickets1',' ' as 'Tickets2'
FROM #Table1 ti
UNION
SELECT ' ' as 'Tickets1', tr.Tickets2 as 'Tickets2'
FROM #table2 tr
) T

How to ignore column in SQL Server

I have this query:
Select *
from
(Select
*
ROW_NUMBER() OVER (PARTITION BY TID ORDER BY TID) AS RowNumber
from
MyTable
where
Eid = 'C1') as a
where
a.RowNumber = 1
and it displays these results:
Column1 Column2 RowNumber
------------------------------
Value1 value2 1
I want to ignore the RowNumber column in the select statement and I don't want to list all columns in select query (100+ columns and given is just an example).
How to do this in SQL Server?
Well, you would have to list all the columns in the outer select, if you use a subquery and row_number() to get a unique row.
An alternative method uses a correlated subquery, but requires having some unique column in the table. If you have one:
select t.*
from mytable t
where t.col = (select max(t2.col) from mytable t2 where t2.tid = t.tid and t2.eid = 'C1');
With the right indexes, this can have better performance than the row_number() version.
If you don't have a unique column, you can do:
select t.*
from (select distinct tid from mytable where eid = 'C1') tc cross apply
(select top 1 t.*
from mytable t
where t.tid = tc.tid and t.eid = 'C1'
) t;
Wrap your query as a subquery and select specific columns from it like so:
SELECT x.Column1, x.Column2
FROM
(
Select * from (Select * ROW_NUMBER() OVER (PARTITION BY TID ORDER BY TID)
AS RowNumber from MyTable where Eid="C1") as a where a.RowNumber=1
) AS x
OR Change your original Select to:
Select a.[Column1], a.[Column2]
from
(
Select * ROW_NUMBER() OVER (PARTITION BY TID ORDER BY TID)
AS RowNumber from MyTable where Eid="C1"
) as a
Where a.RowNumber=1
Replace * from your query in clarify exactly columnd which you whant
select x.Column1, x.Column2 FROM (
Select * from (Select * ROW_NUMBER() OVER (PARTITION BY TID ORDER BY TID)
AS RowNumber from MyTable where Eid="C1") as a where a.RowNumber=1) AS x

Ms sql - update one column table by another row by row

I have got one table (Table1) with some columns filled by data and one empty column. There is another table (Table2) with one column with data. There is no foreign key or any link to that tables just row numbers are equal. I want update empty column of Table1 by data from column of Table2 row by row (row1 from table2 to row1 from table1. Is any way to do it but not using export to file? Is possible to do that using while loop?
If I understand correctly, you can use row_number():
with toupdate as (
select t1.*, row_number() over (order by (select NULL)) as seqnum
from table1 t1
)
update toupdate
set col = t2.col
from (select t2.*, row_number() over (order by (select NULL)) as seqnum
from table2 t2
) t2
where t2.seqnum = t1.seqnum;
Add rownumbers like this and join them:
WITH CTE_TableA AS(
SELECT ColA, ROW_NUMBER() OVER (PARTITION BY ColA ORDER BY ColA) AS RowA
FROM TableA)
,CTE_TableB AS
SELECT ColB, ROW_NUMBER() OVER (PARTITION BY ColB ORDER BY ColB) AS RowB
FROM TableB
SELECT * FROM CTE_TableA AS A
INNER JOIN CTE_TableB AS B ON A.RowA = B.RowB

In an SQL join operation, how to get the rows from the left join and only the aggregate of two columns from the right table

I am trying to SUM the quantity in tpos table and count the distinct number of stores for each item that is in tpos.
For each row in inv_dtl there could be mulitple rows in tpos tables. I would like to put a script together that would give me all the rows from the inv_dtl table and add two aggregate columns sum(tpos.quantiy), count(distinct, tpos.store_number) that matches the join condition.
Here is what I have so far. The aggregates are working but my output contains the number or rows that match in tpos.
For example 1 row in inv_dtl could have 100 rows in tpos. My output should contain 1 row plus the two aggregate columns but my current script generates 100 rows.
WITH FT1 As
(
SELECT * FROM inv_dtl WHERE inv_no IN (16084, 23456, 14789)
),
FT2 As
(
SELECT
FT1.*,
SUM(tpos.quantity) OVER (partition by tpos.item_id) As pos_qty,
DENSE_RANK() OVER (partition by tpos.store_number ORDER BY tpos.item_id ASC) +
DENSE_RANK() OVER (partition by tpos.store_number ORDER BY tpos.item_id DESC)
As unique_store_cnt
FROM FT1
LEFT JOIN tpos
ON tpos.item_id = FT1.ITEM_ID
And tpos.movement_date Between FT1.SDATE And FT1.EDATE
And tpos.store_number != 'CMPNY'
)
SELECT * FROM FT2 ORDER BY ITEM_ID
Just use a conventional GROUP BY which will reduce the number of rows. But as I have no idea what columns you want from the first mentioned table so I have just invented 4 as an example.
WITH
FT1 AS (
SELECT
col1, col2, col3, col4
FROM inv_dtl
WHERE inv_no IN (16084, 23456, 14789)
),
FT3 AS (
SELECT
FT1.col1, FT1.col2, FT1.col3, FT1.col4
, SUM(tpos.quantity) OVER (PARTITION BY tpos.item_id) AS pos_qty
, ROW_NUMBER() OVER (PARTITION BY col1, col2, col3, col4 ASC) +
AS unique_store_cnt
FROM FT1
LEFT JOIN tpos ON tpos.item_id = FT1.ITEM_ID
AND tpos.movement_date BETWEEN FT1.SDATE AND FT1.EDATE
AND tpos.store_number != 'CMPNY'
GROUP BY
FT1.col1, FT1.col2, FT1.col3, FT1.col4
)
SELECT
*
FROM FT3
ORDER BY col1, col2, col3, col4
Do pleae note that RANK() and DENSE_RANK() can repeat numbers if data is of "equal rank". To guarantee a unique integer per row use ROW_NUMBER() instead.

sql query that partitions the data and orders by time and then returns only specific records within a partition

So what I mean exactly is: data is partitioned by name and ordered by date
I would like now to select only those rows in each partition which are coming after the row where NO is null and GENRE is null (after the rowNo 3 in case of the provided example)
So result of the query should return rowNo 4 and 5
Query used:
select
name, no, genre, date,
ROW_NUMBER() OVER(PARTITION BY name, genre ORDER BY date)
from
sourceTable
Assuming there is only one row per name where no and genre are null, you can use
select t1.*
from tablename t1
join tablename t2 on t1.name = t2.name and t2.no is null and t2.genre is null
where t1.date > t2.date
Why wouldn't you just do this?
select t.*
from (select name, no, genre, date,
ROW_NUMBER() OVER(PARTITION BY name, genre ORDER BY date) as rowno
from sourceTable
) t
where rowno > 3;