SQL - Join two tables without a key - sql

Given two tables (count(Table1) <= count(Table2)):
Table1:
record-1
record-2
...
record-k
Table2:
promo-1
promo-2
...
promo-j
Is it possible to join them into the following table? I.e. assign each entry in Table1 some entry in Table2, but that no two entries in Table1 would correspond to the same entry in Table2.
Result:
record-1 promo-i1
record-2 promo-i2
...
record-n promo-in

You could create a fake key using the rownum pseudo-column, and join according to that:
SELECT t1.col1, t2.col2
FROM (SELECT col1, ROWNUM AS rn
FROM table1
ORDER BY col1) t1
JOIN (SELECT col2, ROWNUM AS rn
FROM table2
ORDER BY col2) t2 ON t1.rn = t2.rn
EDIT:
A slightly "clunkier", yet more ANSI-friendly approach would be to use the ROW_NUMBER() window function:
SELECT t1.col1, t2.col2
FROM (SELECT col1, ROW_NUMBER() OVER (ORDER BY col1) AS rn
FROM table1) t1
JOIN (SELECT col2, ROW_NUMBER() OVER (ORDER BY col2) AS rn
FROM table2) t2 ON t1.rn = t2.rn

Related

inserting into a table records from another table with a condition

Let's say I have two tables t1 and t2.
t1 has two integer cols col1 (primary) and col2
t2 has two cols a foreign key of t1.col1 and t2.col2
I want to do the following
Retrieve only the records where t1.col2 is unique OR if t1.col2 is duplicate only those if t2.col2 is not null.
Insert the above records into another summary table, let's say t3
This is what I tried:
insert into t3 (col1,col2)
select col1, col2
from t1
where t.col1 in (select A.col1 from t1 as A
group by 1
having count(*) > 1
union
select col1, col2
from t1, t2
where t.col1 in (select A.col1 from t1 as A
group by 1
having count(*) > 1
and t2.col2 is not null;
While the 'union qry' works on its own, the insert is not happening.
Any ideas or any other efficient way to achieve this please
You can select the records you want using:
select t1.*
from (select t1.*, count(*) over (partition by col2) as cnt
from t1
) t1
where cnt = 1 or
exists (select 1 from t2.col1 = t1.col1 and t2.col2 is null);
The rest is just an insert.

where column in from another select results with limit (mysql/mariadb)

when i run this query returns all rows that their id exist in select from table2
SELECT * FROM table1 WHERE id in (
SELECT id FROM table2 where name ='aaa'
)
but when i add limit or between to second select :
SELECT * FROM table1 WHERE id in (
SELECT id FROM table2 where name ='aaa' limit 4
)
returns this error :
This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
You are using LIMIT without an ORDER BY. This is generally not recommended because that returns an arbitrary set of rows -- and those can change from one execution to another.
You can convert this to a JOIN -- fortunately. If id is not duplicated in table2:
SELECT t1.*
FROM table1 t1 JOIN
(SELECT t2.id
FROM table2 t2
WHERE t2.name = 'aaa'
LIMIT 4
) t2
USING (id);
If id can be duplicated in table2, then:
SELECT t1.*
FROM table1 t1 JOIN
(SELECT DISTINCT t2.id
FROM table2 t2
WHERE t2.name = 'aaa'
LIMIT 4
) t2
USING (id);
Another fun way uses LIMIT:
SELECT t1.*
FROM table1 t1
WHERE id <= ANY (SELECT t2.id
FROM table2
WHERE t2.name = 'aaa'
ORDER BY t2.id
LIMIT 1 OFFSET 3
);
LIMIT is allowed in a scalar subquery.
You can use an analytic function such as ROW_NUMBER() in order to return one row from the subquery. I suppose, this way no problem would occur like raising too many rows issue :
SELECT * FROM
(
SELECT t1.*,
ROW_NUMBER() OVER (ORDER BY t2.id DESC) AS rn
FROM table1 t1
JOIN table2 t2 ON t2.id = t1.id
WHERE t2.name ='aaa'
) t
WHERE rn = 1
P.S.: Btw, id columns are expected to be primary keys of your tables, aren't they ?
Update ( depending on your need in the comment ) Consider using :
SELECT * FROM
(
SELECT j.*,
ROW_NUMBER() OVER (ORDER BY j.id DESC) AS rn2
FROM job_forum j
CROSS JOIN
( SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY t2.id ORDER BY t2.id DESC) AS rn1
FROM table2 t2
WHERE t2.name ='aaa'
AND t2.id = j.id ) t2
WHERE rn1 = 1
) jj
WHERE rn2 <= 10

#1093 Table 'table' is specified twice, both as a target for 'DELETE' and as a separate source for data

not getting desire result in mysql query
i have searched a lot but didn't find solution
DELETE FROM table1 WHERE username NOT IN (select t1.id from table1 as t1
inner join table1 as t2 on t1.username = t2.username and t1.id <= t2.id
group by t1.username , t1.id having count(*) <= 5 order by t1.username , t1.id desc);
Output is as follows:-
should work for you
delete from
table1
where
id in ( select
id
from
( select
*,
row_number() over( partition by
username
order by
id desc) as rn
from
table1)
where
rn > 5)
You seem to want to keep the most recent five ids for each user name. I think the simplest method uses window functions:
delete t1
from table1 t1 join
(select t1.*, row_number() over (partition by username order by id desc) as seqnum
from table1 t1
) tt1
on t1.username = tt1.username and
t1.id = tt1.id
where tt1.seqnum > 5;

How to achieve the below requirements in sql

I have table like below
the result set should contain 4,5 since it has count of (c2) and (c3) >1
You can use exists :
select t.*
from table t
where exists (select 1 from table t1 where t1.col2 = t.col2 and t1.col1 <> t.col1);
JOIN a subquery that returns the duplicated col2 values:
select t1.*
from tablename t1
join (select col2 from tablename
group by col2 having count(*) > 1) t2
on t1.col2 = t2.col2
I would use window functions:
select t.*
from (select t.*,
count(*) over (partition by c2) as c2_cnt,
count(*) over (partition by c3) as c3_cnt
from t
) t
where c2_cnt > 1 and c3_cnt > 1;
As you changed your requirement so i changed my query
select t1.* from table_name t1 where
exists( select 1 from table_name t2 where t2.col2=t1.col2
and t2.c3=t1.c3
group by t2.c2,t2.c3
having count(*)>1
)

Left Join without duplicate rows 1 to 1 join. Make each row in one table only join to one row in the other table

I'm trying to join table 1 to table 2 to get table 3. (See desired output) However, I can't seem to get it to work since there are so many options since the table only contains one value. A left join doesn't seem to work.
I found this: Left Join without duplicate rows from left table
which seems to match my use case, but Outer Apply is not in PrestoDB.
I essentially want to match each row in T1 with a single one in T2.
If I understand correctly, you can use row_number():
select t1.*, t2.col3
from t1 left join
(select t2.*, row_number() over (partition by col2 order by col3 nulls last) as seqnum
from t2
) t2
on t2.col2 = t1.col2 and t2.seqnum = 1;
If you don't have proper keys you get an m:n-join instead of 1:n. You can calculate a row number for both tables which acts (in combination with col2) as key for the following join:
select t1.col1, t1.col2, t2.col3
from
(
select t1.*,
row_number() over (partition by col2 order by col2) as rn
from t1
) as t
left join
(
select t2.*,
row_number() over (partition by col2 order by col2) as rn
from t2
) as t2
on t1.col2 = t2.col2
and t1.rn = t2.rn;