Combine multiple tables in one - sql

If I have tlb1 as :
col1
1
2
3
Now I have tlb2 as:
col2 col3
4 Four
5 Five
6 SIX
No I have tlb3 as
col4 col5
sample14 sample15
sample24 sample25
sample34 sample35
What can be the query if I want result as :
col1 col2 col3 col4 col5
1 4 Four sample14 sample15
2 5 Five sample24 sample25
3 6 Six sample34 sample35
I tried with :
select ( (select * from tlb1), (select * from tlb2),(select * from tlb3)) T
But this failed.
Please help me.

with t1 as (select col1, row_number() over (order by col1) rn from tbl1 ),
t2 as (select col2,col3, row_number() over (order by col2) rn from tbl2),
t3 as ( select col4,col5, row_number() over (order by col4) rn from tbl3)
select t1.col1,t2.col2,t2.col3,t3.col4,t3.col5
from t1 full outer join t2 on t1.rn = t2.rn
t3 full outerjoin t2 on t2.rn = t3.rn
try something like this...

Related

how to extract the rows where a group appears more than a certain number of times

I have the following table
col1 col2 col3 key
A B C 1
A B B 2
A B B 3
A B D 4
B D C 5
I would like to extract the rows where the group col1, col2, col3 appears more than once in the table.
A B B 2
A B B 3
So far, I have:
SELECT col1, col2, col3, count(*)
FROM db.table
GROUP BY col1, col2, col3
HAVING count(*) > 1
col1 col2 col3 count(*)
A B B 2
Is there a way to extract those rows with A B B without having to join the final table with the initial table?
You could use exists logic:
SELECT col1, col2, col3, "key"
FROM yourTable t1
WHERE EXISTS (SELECT 1 FROM yourTable t2
WHERE t2.col1 = t1.col1 AND t2.col2 = t1.col2 AND
t2.col3 = t1.col3 AND
t2."key" <> t1."key");
Try below query with CTE
with MyCTE
as
(
select col1,col2,col3,Key,COUNT(*) over(PARTITION BY col1,col2,col3 order
by col1,col2,col3) as Duplicate from yourtable
)
select col1,col2,col3,key from MyCTE where Duplicate>1

Why do left and right join ignore some values in a query?

I have a table with 3 columns and these values:
col1 col2 col3
-------------------
1 2 8
1 3 5
1 10 15
2 4 6
2 9 7
3 5 6
I join a query LEFT JOIN and RIGHT JOIN a grouping and counting query
for each number (MS-ACCESS).
SELECT Col1 AS Num, t1.CON1, t2.CON2, t3.CON3
FROM
(((SELECT col1, COUNT(col1) AS CON1 FROM table GROUP BY col1) AS t1
LEFT JOIN (SELECT col2, COUNT(col2) AS CON2 FROM table GROUP BY col2) AS t2
ON t1.col1 = t2.col2)
LEFT JOIN (SELECT col3, COUNT(col3) AS CON3 FROM table GROUP BY col3) AS t3
ON t2.col2 = t3.col3)
UNION
SELECT col3 AS Num, t1.CON1, t2.CON2, t3.CON3
FROM
(((SELECT col1, COUNT(col1) AS CON1 FROM table GROUP BY col1) AS t1
RIGHT JOIN (SELECT col2, COUNT(col2) AS CON2 FROM table GROUP BY col2) AS t2
ON t1.col1 = t2.col2)
RIGHT JOIN (SELECT col3, COUNT(col3) AS CON3 FROM table GROUP BY col3) AS t3
ON t2.col1 = t3.col3)
It results like this:
Num CON1 CON2 CON3
--------------------------
1 3
2 2 1
3 1 1
5 1 1
6 2
7 1
8 1
15 1
But this query ignores count of values from column 2 of table
Num CON2
---------------
4 1
9 1
10 1
What is missing in my query?
If you want to count each value and the number of times in each column, then use union all to split the data and then group by:
select num, sum(col1), sum(col2), sum(col3)
from ((select col1 as num, 1 as col1, 0 as col2, 0 as col3
from t
) union all
(select col2 as num, 0 as col1, 1 as col2, 0 as col3
from t
) union all
(select col3 as num, 0 as col1, 0 as col2, 1 as col3
from t
)
) as x
group by num
order by num;
This gives correct totals, but I can't figure how to summarise the results (it lists 3 twice, for example) ...
(
(SELECT col1 as num, COUNT(col1) AS CON1, null as CON2, null as CON3 FROM mytable t1
LEFT JOIN (SELECT col2, COUNT(col2) AS CON2 FROM mytable GROUP BY col2) t2
ON t1.col1 = t2.col2
LEFT JOIN (SELECT col3, COUNT(col3) AS CON3 FROM mytable GROUP BY col3) t3
ON t2.col2 = t3.col3
GROUP BY t1.col1)
UNION
(SELECT col2 as num, null as CON1, COUNT(col2) AS CON2, null as CON3 FROM mytable t4
left JOIN (SELECT col1, COUNT(col1) AS CON1 FROM mytable GROUP BY col1) t5
ON t4.col2 = t5.col1
left JOIN (SELECT col3, COUNT(col3) AS CON3 FROM mytable GROUP BY col3) t6
ON t4.col2 = t6.col3
GROUP BY t4.col2)
UNION
(SELECT col3 as num, null as CON1, null as CON2, COUNT(col3) AS CON3 FROM mytable t7
left JOIN (SELECT col1, COUNT(col1) AS CON1 FROM mytable GROUP BY col1) t8
ON t7.col3 = t8.col1
left JOIN (SELECT col2, COUNT(col2) AS CON3 FROM mytable GROUP BY col2) t9
ON t7.col3 = t9.col2
GROUP BY t7.col3)
)
RESULTS:
num CON1 CON2 CON3
1 3
2 1
2 2
3 1
3 1
4 1
5 1
5 1
6 2
7 1
8 1
9 1
10 1
15 1
... Anyone?
SQL TEST: https://sqltest.net/#979886

SQL Server : get max of the column2 and column3 value must be 1

I have an output of some part of my stored proedure like this:
col1 col2 col3 col4
--------------------------
2016-05-05 1 2 2
2016-05-05 1 3 32
2016-05-12 2 1 11
2016-05-12 3 1 31
Now I need to get result based on this condition
col2 = 1 and col3 = max or col3 = 1
and col2 = max
The final result should be
col1 col2 col3 col4
-------------------------
2016-05-05 1 3 32
2016-05-12 3 1 31
Not sure if thats the most efficient way , but you can use ROW_NUMBER() :
SELECT * FROM (
SELECT t.*,
ROW_NUMBER() OVER(PARTITION BY t.col1 ORDER BY t.col3 DESC) as rnk,
WHERE t.col2 = 1
UNION ALL
SELECT t.*,
ROW_NUMBER() OVER(PARTITION BY t.col1 ORDER BY t.col2 DESC) as rnk,
WHERE t.col3 = 1) tt
WHERE rnk = 1
This will give you all the records with
(col2=1 and col3=max) or (col3=1 and col2=max)
This is a bit tricky. Your data has no ambiguities, such as duplicate maximuma in col4 or "1" values in both col2 and col3.
The following is a direct translation of the logic in your question:
select t.*
from t
where t.col4 = (select max(t2.col4)
from t t2
where t2.col1 = t.col1 and (t2.col2 = 1 or t2.col3 = 1)
);
Try this. Note if there are more than 1 same max value, then you need all of those in output. And it will work for all scenarios, even when col1 is not in sync with col2 and col3.
I am first finding highest values of col2 and col3 and assigning them value as 1. Then in outer query, I am using your join condition. Demo created for Postgres DB as SQLServer wasn't available.
SQLFiddle Demo
select col1,col2,col3,col4
from
(
select t.*,
RANK() OVER(ORDER BY col3 DESC) as col3_max,
RANK() OVER(ORDER BY col2 DESC) as col2_max
from your_table t
) t1
where
(col2=1 and col3_max=1)
OR
(col3=1 and col2_max=1)
Alternative way:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY iif(col2 = 1, col3, col2) DESC) as r
FROM tbl) t
WHERE r = 1

How to select duplicate columns data from table

Have table like :
col1 col2 col3 col4 col5
test1 1 13 15 1
test2 1 13 15 4
test3 2 7 3 5
test4 3 11 14 18
test5 3 11 14 8
test6 3 11 14 11
Want select col1,col2,col3,col4 data where col2,col3,col4 are duplicates
for example it must be :
col1 col2 col3 col4
test1 1 13 15
test2 1 13 15
test4 3 11 14
test5 3 11 14
test6 3 11 14
How to do it ?
Presuming SQL-Server >= 2005 you can use COUNT(*) OVER:
WITH CTE AS
(
SELECT col1, col2, col3, col4, cnt = COUNT(*) OVER (PARTITION BY col2, col3, col4)
FROM dbo.TableName t
)
SELECT col1, col2, col3, col4
FROM CTE WHERE cnt > 1
Demo
If I understand correctly:
select col1, col2, col3, col4
from table t
where exists (select 1 from table t2 where t2.col1 = t.col1 and t2.col1 <> t.col1) and
exists (select 1 from table t2 where t2.col2 = t.col2 and t2.col1 <> t.col1) and
exists (select 1 from table t2 where t2.col3 = t.col3 and t2.col1 <> t.col1);
Simple Join can work
select m1.col1,m1.col2,m1.col3,m1.col4 from Mytable m1
join Mytable m2
on m1.col2 =m2.col2
and m1.col3=m2.col3
and m1.col4 =m2.col4
You can use the following code for that:
SELECT * FROM your_table
MINUS
SELECT DISTINCT * FROM your_table
EDIT: sorry this works only for complete duplicates. If you want to exclude the first column, you can use
SELECT col2,col3,col4 FROM your_table
MINUS
SELECT DISTINCT col2,col3,col4 FROM your_table
and afterwards make a join with the table itself (ON its primary keys).

Oracle - Find matched records with a different value for one field

Suppose I have the following table in my Oracle DB:
Col1: Col2: ... Coln:
1 a ... 1
1 a ... 1
1 b ... 1
1 b ... 1
1 c ... 1
1 a ... 1
2 d ... 1
2 d ... 1
2 d ... 1
3 e ... 1
3 f ... 1
3 e ... 1
3 e ... 1
4 g ... 1
4 g ... 1
And, what I want to get is a distinct list of records where, for Col1, Col2 is different - Ignoring any times that Col2 matches for all of Col1.
So, in this example I would like to get the result set:
Col1: Col2:
1 a
1 b
1 c
3 e
3 f
Now, I figured out how to do this using a query that feels fairly complex for the question at hand:
With MyData as
(
SELECT b.Col1, b.Col2, count(b.Col2) over(Partition By b.Col1) as cnt from
(
Select distinct a.Col1, a.Col2 from MyTable a
) b
)
select Col1, Col2
from MyData
where cnt > 1
order by Col1
What I'm wondering is what is a nicer way to do this - I didn't manage to do this using GROUP BY & HAVING and probably think this could maybe be done using a self-join... This is more of a quetion to see / learn new ways to get a result in a nicer (and perhaps more efficient) query.
Thanks!!!
Try this query:
SELECT distinct *
FROM table1 t1
WHERE EXISTS
( SELECT 1 FROM table1 t2
WHERE t1.col2 <> t2.col2
AND t1.col1 = t2.col1
)
order by 1,2
demo: http://www.sqlfiddle.com/#!4/9ce10/12
----- EDIT -------
Yes, there are other ways to do this:
SELECT distinct col1, col2
FROM table1 t1
WHERE col2 <> ANY (
SELECT col2 FROM table1 t2
WHERE t1.col1 = t2.col1
)
order by 1,2;
SELECT distinct col1, col2
FROM table1 t1
WHERE NOT col2 = ALL (
SELECT col2 FROM table1 t2
WHERE t1.col1 = t2.col1
)
order by 1,2
;
SELECT distinct t1.col1, t1.col2
FROM table1 t1
JOIN table1 t2
ON t1.col1 = t2.col1 AND t1.col2 <> t2.col2
order by 1, 2
;
SELECT t1.col1, t1.col2
FROM table1 t1
JOIN table1 t2
ON t1.col1 = t2.col1
GROUP BY t1.col1, t1.col2
HAVING COUNT( distinct t2.col2 ) > 1
order by 1, 2
;
SELECT t1.col1, t1.col2
FROM
table1 t1
JOIN (
SELECT col1
FROM table1
GROUP BY col1
HAVING COUNT( distinct col2 ) > 1
) t2
ON t1.col1 = t2.col1
GROUP BY t1.col1, t1.col2
ORDER BY t1.col1, t1.col2
;
Demo --> http://www.sqlfiddle.com/#!4/9ce10/33
Try them all, I really don't know how they will perform on your data.
However, creating a composite index:
CREATE INDEX name ON table1( col1, col2 )
will most likely speed up all of these queries.
Here is a method that uses aggregation and an analytic function:
with t as (
select col1, col2,
count(*) over (partition by col1) as cnt
from table1
group by col1, col2
)
select col1, col2
from t
where cnt > 1;
What I would like to do is:
select col1, col2,
count(*) over (partition by col1) as cnt
from table1
group by col1, col2
having count(*) over (partition by col1) > 1;
However, this is not valid SQL because the analytic functions are not allowed in the having clause.