write a sub select query - sql

I have two tables with one to many relationship. I want to write a query which outputs all records from table with one record and only one record from the table having many records.
So the table having many records with first show the most occurring record. If there are equal occurrences then it will Order by ascending and show the first record.
Table1
Col1 Col2 Col3
a1 1 4
a2 2 5
a3 3 6
Table2
Col1 Col4
a1 10
a1 11
a1 22
a1 11
a2 10
a2 11
a3 19
a3 22
a3 22
a3 23
Query output:
Col1 Col2 Col3 Col4
a1 1 4 11
a2 2 5 10
a3 3 6 22
Hope I made it clear.

First you need to use a group by along with a min() to get the smallest number from table2, then you join to table1 to get the columns you need. I've used a left join as I'm assuming there may not be a match in table2 but you can change it to an INNER JOIN if there are always 1 or more corresponding records in table2.
SELECT a.col1, a.col2, a.col3, b.col4
FROM table1 a
LEFT JOIN (
SELECT col1, col4 = MIN(col4)
FROM table2
GROUP BY col1
) b
ON a.col1 = b.col1

Related

Grouping the common values in Oracle

I have a table with sample values as below
In this table, all the values in Col1 will have its supporting values in Col2. The values A1 and A2 are like master values and they will never appear in Col2. I need to make an output displaying this master values in a new column like below
What would be the best way to achieve this in Oracle SQL?
Looks like a hierarchical query:
SQL> select connect_by_root t.col1 as main,
2 t.col1,
3 t.col2
4 from test t
5 start with t.col1 in ('A1', 'A2')
6 connect by t.col1 = prior t.col2
7 order by main, t.col1, t.col2;
MAIN COL1 COL2
----- ----- -----
A1 A1 B1
A1 A1 B2
A1 A1 B3
A1 B1 C1
A1 B2 C2
A1 C1 D1
A2 A2 E1
A2 A2 E2
A2 E1 F1
A2 E1 F2
10 rows selected.
SQL>

How to get rows having uncommon values in two tables in SQL?

Suppose I have a table a with columns A1,A2,A3,A4 and table b with columns B1,B2,B3,B4.
I want to find a records which are having different values in column A1,A2 and B1,B2
Ex.
A1 A2 A3 A4 B1 B2 B3 B4
12 10 10 12 12 10 10 12
14 14 10 12 15 10 10 12
15 10 10 10 15 10 10 10
IT SHOULD RETURN
14 14 10 10
I tried:
SELECT A1,A2
FROM A
EXCEPT
SELECT B1,B2
FROM B;
However, it returned on A1,A2 columns instead of all columns
use left join
select a.* from tableA a
left join tbaleB b
on a.A1=b.B1 and a.A2=b.B2 and a.A3=b.B3 and a.A4=b.B4
where b.B1 is null
You can try below using left join
select * from tableA
left join tableB on A1=B1 and A2=B2
where B1 is null and B2 is null
I would use not exists:
select a.*
from a
where not exists (select 1
from b
where a.a1 = b.b1 and a.a2 = b.b2
);

How can I merge rows and columns from two sql tables into one table

I searched for a while but I couldn't find something similar.
I have two tables with data and I want to merge those two in two one.
Tbl1
id nr val1
1 a1 123
2 a2 124
3 a3 125
Tbl2
id nr val2
5 a1 223
6 a2 224
7 a4 225
Resulting table should be something like this.
Tbl
nr val1 val2
a1 123 223
a2 124 224
a3 125 0
a4 0 225
Any help would be appreciated. Thanks in advance.
It is MS SQL and I tried union and join. But they don't do.
if you use MS SQL then you could try full outer join and Isnull function to get the result you need.
SELECT Isnull(tbl1.nr, tbl2.nr) nr,
Isnull(tbl1.val1, 0) val1,
Isnull(Tbl2.val2, 0) val2 FROM tbl1 FULL OUTER JOIN tbl2 ON tbl1.nr = tbl2.nr
You can do it by doing a FULL OUTER JOIN and COALESCE the columns together.
SELECT COALESCE(tbl1.nr,tbl2.nr) AS nr,tbl1.val1,tbl2.val2
FROM tbl1 FULL OUTER JOIN tbl2
ON tbl1.nr = tbl2.nr;
SELECT NVL(a1.nr,b1.nr) as nr,
NVL(a1.val1,0) AS val1,
NVL(b1.val2,0) AS val2
FROM table1 a1
FULL OUTER JOIN table2 b1 ON a1.nr = b1.nr
ORDER BY a1.nr;

SQL: Copy data from one table into another using unique key present in both tables

I have two tables that contain the same unique key. I need to match those keys and then copy data from table 2 into table 1
Original:
Key COL1 COL2 Key COL3
1 01 NULL 1 05
2 02 NULL 2 12
3 03 NULL 3 27
Required:
Key COL1 COL2 Key COL3
1 01 05 1 05
2 02 12 2 12
3 03 27 3 27
Thank you for the help.
Your best answer is probably an UPDATE FROM a lookup based on the two tables (for SQL Server, some say use JOIN, some say there's no need, and without the join is more concise).
See some examples here: SQL update from one Table to another based on a ID match
For convenience, here's a query adapted for your scenario:
UPDATE Table1 SET
Col1 = Table2.Col1,
Col2 = Table2.Col2,
Col3 = Table2.Col3,
FROM Table2
WHERE Table2.Key = Table1.Key
TRY this:
update table1
set col2 = (
select col3
from table2
where table2.key=table1.key
)
where exists (
select *
from table2
where table2.key=table1.key
);

SQL loop with a column number

I have a table with 3 col and 4 row.
Col1 Col2 Col3
Row1 A1 B1 1
Row2 A2 B2 0
Row3 A3 B3 3
Row4 A4 B4 1
A select * from [table] returns:
A1 B1 1
A2 B2 0
A3 B3 3
A4 B4 1
I Want a select that give:
A1 B1 1
A3 B3 3
A3 B3 3
A3 B3 3
A4 B4 1
Col3 gives the number of row return.
Start with a numbers table... a table with one row for each number, going up as high as the largest possible value in your Col3. It will look something like this:
Table: Numbers
Value
-----
1
2
3
4
5
...
Then you you can JOIN to this table using an inequality:
SELECT Col1, Col2, Col3
FROM [table] t
INNER JOIN NUMBERS n ON n.Value <= t.Col3
This will make your Row3 value match to the Numbers table 3 times, duplicating that row in the results, whereas the Row2 value won't match any records from the Numbers table, removing it from the results.
There are several options for generating a Numbers table you can look at here:
What is the best way to create and populate a numbers table?
With the Option 6 from that question:
WITH Numbers AS (
SELECT TOP 10000 row_number() over(order by t1.number) as [Value]
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
)
SELECT Col1, Col2, Col3
FROM [table] t
INNER JOIN NUMBERS n ON n.Value <= t.Col3
Note that this is overkill for your sample data, which only goes to 3. For anything less than about 50, you could just hard-code the table. I'm assuming your real data goes much higher.