Combine between parallel rows only, in SQL - sql

Given two tables with different rows and values,how can I combine this two tables so the first row of the first table will be combined in a new row with the first row of the second table and so on.. The requirement is that unlike Cartesian product, only the parallel rows will be combined together on the new table.
I am working with PL/SQL Developer
For example(the values are just an example as well):
Table 1:
LongId
100
200
300
Table 2:
Id
1
2
3
The new table:
Id LongId
1 100
2 200
3 300

Use:
SELECT id, longid
FROM (
SELECT t.*,
row_number() over( order by LONGID ) as XXX
FROM table1 t
)
JOIN (
SELECT t.*,
row_number() over( order by id) as XXX
FROM table2 t
)
USING ( xxx )
Demo: http://sqlfiddle.com/#!4/ba9b1/5
| ID | LONGID |
|----|--------|
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |

You can use row_number() on both tables and then use that to join on.
SELECT t2.id, t1.longid
FROM
(SELECT table1.*, ROW_NUMBER() OVER (ORDER BY longid) AS rn
FROM table1) t1
JOIN
(SELECT table2.*, ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM table2) t2 on t1.rn = t2.rn

Related

Merging two tables with no unique keys without row number

I have two tables
Table A:
Name
----
Andy
Greg
Table B:
Value
-----
1
2
I want to merge these two tables into one:
Table C:
Result
------
Andy 1
Greg 2
Note:-
without changing the order. I cannot use row numbers as I am using Apache Calcite and it doesn't support that right now.
Is this possible?
WITH X AS
(
SELECT * FROM
(
SELECT NAME AS Val1,
(SELECT Count(*) from #TableA a1 WHERE a1.Name < a2.Name) AS myRowNumber1 FROM #TableA a2
)a1
INNER JOIN
(
SELECT Id AS Val2,
(SELECT Count(*) from #TableB a1 WHERE a1.Id < a2.Id) AS myRowNumber2 FROM #TableB a2
)b1
ON a1.myRowNumber1=b1.myRowNumber2
)
SELECT Val1 +' '+ Val2 AS Result FROM X
You can use Count(*) instead of Row_Number()
OutPut:-
Result
---------
Andy 1
Greg 2
Create a new column as an identifier
SELECT *, ROW_NUMBER() OVER(PARTITION BY NAME ORDER BY NAME) AS id
INTO #NAMES
FROM TABLE1
SELECT *, ROW_NUMBER() OVER(PARTITION BY VALUE ORDER BY VALUE) AS id
INTO #VALUES_TABLE
FROM TABLE2
And then join by the row number that will be called id
SELECT *
FROM #NAMES t1
LEFT JOIN #VALUES_TABLE t2
ON t1.id = t2.id
Calcite does not have a function exactly like Oracle's ROWNUM pseudocolumn but it does have the standard SQL window function ROW_NUMBER(). You can use it as follows:
create table a as select * from (values ('Andy'), ('Greg')) as t (name);
create table b as select * from (values (1), (2)) as t (v);
select *
from (select name, row_number() over () as id from a)
join (select v, row_number() over () as id from b)
using (id);
+----+------+---+
| ID | NAME | V |
+----+------+---+
| 1 | Andy | 1 |
| 2 | Greg | 2 |
+----+------+---+
(2 rows)
If you want deterministic order, you can change over () to, say, over (order by name desc).

Query to get all distinct lines adding a column indicating a sum of each duplicate

What I'm Looking for:
I need to have a list from SQL server getting all IDs, but each ID have multiples lines.
Some lines from each ID are systems update so do not need to take care about them in my query.
In another words:
I need to get the whole list, counting all lines that are not from system for each ID.
The Database its looks like below:
ID | linenumber| data, data, ... data|Requesto| data, data
1 | 1 |.....................|JUAN |...........
1 | 2 |.....................|SYSTEM |...........
2 | 1 |.....................|Matias |...........
2 | 2 |.....................|Matias |...........
2 | 3 |.....................|Matias |...........
And I need to get:
ID | CantRoWs |.....................|WHO is |...........
1 | 1 |.....................|JUAN |...........
2 | 3 |.....................|Matias |...........
I was thinking about using a temp query like below but it does not work.
with temp as
(
SELECT OVER (PARTITION BY szCID ORDER BY gdReceived desc) as RowNum,*
FROM TABLE1;
)
SELECT *, (Select count(szCID) from TABLE1 where szAccount <> 'system') AS Hits From temp
WHERE RowNum = 1
Any ideas?
I would suggest you start by using row_number() and count() inside the common table expression:
WITH temp
AS (
SELECT
*
, ROW_NUMBER() OVER (PARTITION BY szCID ORDER BY gdReceived DESC) AS RowNum
, COUNT(*) OVER (PARTITION BY szCID) as hits
FROM TABLE1
WHERE szAccount <> 'system'
)
SELECT
*
FROM temp
WHERE RowNum = 1

Selecting compared pairs from table

I don't really know how to describe it. I have a table:
ID | Name | Date
-------------------------
1 | Mike | 01.01.2016
1 | Michael | 02.03.2016
2 | Samuel | 23.12.2015
2 | Sam | 05.03.2015
3 | Tony | 02.04.2012
I want to select pairs of IDs and Names with latest dates in each pair. The result here should be:
ID | Name | Date
-------------------------
1 | Michael | 02.03.2016
2 | Samuel | 23.12.2015
3 | Tony | 02.04.2012
How do I achieve this?
Oracle Database 11g
You can do it using the ROW_NUMBER() analytic function:
SELECT id, name, "date"
FROM (
SELECT t.*,
ROW_NUMBER() OVER ( PARTITION BY id ORDER BY "date" DESC ) rn
FROM table_name t
)
WHERE rn = 1
This requires only a single table scan (it does not have a self-join or correlated sub-query - i.e. IN (...) or EXISTS(...)).
Have a sub-select that returns each id and it's max date:
select * from table
where (id, date) in (select id, max(date) from table group by id)
You can use NOT EXISTS() :
SELECT * FROM YourTable t
WHERE NOT EXISTS(SELECT 1 FROM YourTable s
WHERE t.id = s.id and s.date > t.date)
Possibly the most efficient method is:
select t.*
from table t
where t.date = (select max(date) from table t2 where t2.id = t.id);
along with an index on table(id, date).
This version should scan the table and look up the correct value in the index.
Or, if there are only three columns, you can use keep:
select id, max(date) as date,
max(name) keep (dense_rank first order by date desc) as name
from table
group by id;
I have found that this version works very well in Oracle.

Getting distinct result with Oracle SQL

I have the following data structure
ID | REFID | NAME
1 | 100 | A
2 | 101 | B
3 | 101 | C
With
SELECT DISTINCT REFID, ID, NAME
FROM my_table
ORDER BY ID
I would like to have the following result:
1 | 100 | A
2 | 101 | B
Colum NAME and ID should contain the MIN or FIRST value.
But actually I get stuck at using MIN/FIRST here.
I welcome every tipps :-)
select id,
refid,
name
from (select id,
refid,
name,
row_number() over(partition by refid order by name) as rn
from my_table)
where rn = 1
order by id
You can use a subquery to do this.
WITH Q AS
( SELECT MIN(NAME) AS NAME, REFID FROM T GROUP BY REFID )
SELECT T.ID, T.REFID, T.NAME
FROM T
JOIN Q
ON (T.NAME = Q.NAME)
Also, note that SQL tables have no order. So there's no "First" value.

Select only one row with same key value from a table

I have this table:
reg_no | cname | no
1 | X | 1
1 | Y | 2
2 | X | 1
2 | Y | 2
What I want to do is to select all that rows but I only want one row for each reg_no when I arrange it in desc (it should only get the row with highest no for each reg_no).
The output should be:
1 Y 2
2 Y 2
Use Row_Number() window function
select Reg_no,C_name,no from
(
select row_number() over(partition by reg_no order by no desc) Rn,*
from yourtable
) A
where rn=1
or ANSI SQL standard will work in sql server 2000. Find the max no in each reg_no then join the result back to the main table.
select A.Reg_no,A.C_name,A.no
from yourtable As A
Inner Join
(
select max(no) As no,Reg_no
from yourtable
group by Reg_No
) As B
on A.No=B.No and A.Reg_No=B.Reg_no
In MSSQL using CROSS APPLY this would be
SELECT DISTINCT
r1.reg_no, r2.cname, r2.no
FROM
table_name r1
CROSS APPLY
(SELECT TOP 1
r.cname, r.no
FROM
table_name r
WHERE r1.reg_no = r.reg_no
ORDER BY r.no DESC) r2