Fetching records using join - sql

Below is sample data and a query which returns the result.
create table tab1 (grp_id number, mid number);
create table tab2 (grp_id number, mid number);
insert into tab1 values(1, 5);
insert into tab1 values(1, 6);
insert into tab1 values(1, 7);
insert into tab1 values(1, 8);
insert into tab1 values(2, 9);
insert into tab1 values(2, 10);
insert into tab2 values(1, 5);
insert into tab2 values(1, 6);
-----------------------------------------
select *
from tab1 t1, tab2 t2
where t1.mid = t2.mid(+)
and t1.grp_id in (select grp_id from tab2)
;
| GRP_ID | MID | GRP_ID | MID |
|--------|-----|--------|--------|
| 1 | 5 | 1 | 5 |
| 1 | 6 | 1 | 6 |
| 1 | 7 | (null) | (null) |
| 1 | 8 | (null) | (null) |
Can I have above result without using In or Exists clause.. just by using join left right or case. Please do consider that this is sample data
Please help thanks.

you can use a correlated query where the columns from the outer query goes in as a parameter to the inner query.
this is the only solution:
select t1.grp_id,t1.mid ,(select t2.grp_id from Tab2 t2 where
t1.grp_id=t2.grp_id and t1.mid=t2.mid ),
(select t2.mid from Tab2 t2 where t1.mid=t2.mid and t1.grp_id=t2.grp_id)
from tab1 t1 where t1.grp_id=1
;
check http://sqlfiddle.com/#!4/f9113e/2
Thanks!!!!

Yes, you can get the results by using a left join directly
select t1.grp_id as grp_id_1,t1.mid as mid_1,
t2.grp_id as grp_id_2,t2.mid as mid_2
from tab1 t1
left join tab2 t2 on t1.grp_id=t2.grp_id and t1.mid=t2.mid
where t1.grp_id=1;
Demo

Related

SQL query returning all rows from Table2

I am trying to join 2 tables and return data if the Table1.codeId is presented on Table2 OR if Table1.codeId = 0. However, It retrieves the data from Table2.
Table1 {
name nvarchar,
codeId int
}
| name | codeId |
|--------|--------|
| Bob | 1 |
| Bob | 2 |
| Chris | 0 |
Table2 {
id int,
codeName nvarchar
}
| id | codeName |
|------|----------|
| 1 | Engineer |
| 2 | Doctor |
| 3 | Dentist |
| 4 | Pilot |
| 5 | Mechanic |
SELECT t1.name, t2.codeName
FROM dbo.Table1 t1, dbo.Table2 t2
WHERE (t1.codeId = t2.id OR t1.codeId = 0)
Expected result:
Bob, 1
John, 2
Chris, 0
You are not required to use Join at all for such condition.
You can use subquery as following, it return same result as your expectation
select name,codeid from table1 where codeid in (select id from table2)
or codeid=0
What if you do it in two separates queries ?
Looking at the outcome, the problem must come from the WHERE clause. The OR seem to always be triggered.
So maybe splitting could do it
SELECT t1.name, t2.codeName
FROM dbo.Table1 t1, dbo.Table2 t2
WHERE (t1.codeId = t2.id)
SELECT t1.name, t2.codeName
FROM dbo.Table1 t1, dbo.Table2 t2
WHERE (t1.codeId = 0)
You can use a left join. Use it to select where there is a code match in Table2 or the code_id is 0.
create table Table1
(
name nvarchar(50),
codeId int
)
create table Table2
(
id int,
codeName nvarchar(50)
)
insert into Table1
VALUES
('Bob', 1),
('John', 2),
('Chris', 0),
('Tom', -1)
-- This should be excluded .. since -1 code doesn't exist in Table2
insert into Table2
VALUES
(1, 'Engineer'),
(2, 'Doctor'),
(3, 'Dentist'),
(4, 'Pilot'),
(5, 'Mechanic')
SELECT t1.name, t1.codeId
FROM dbo.Table1 t1
LEFT JOIN dbo.Table2 t2 ON t1.codeId = t2.id
WHERE t2.id is not NULL or t1.codeId = 0
You have to use left outer join.
please find below query
Select codeid,name
FROM Table1
LEFT OUTER JOIN Table2
ON Table1.codeId=Table2.id;

Nested Insert query

I'm trying to write a nested insert into query and I want to insert the values, which are inserted in "Table1", in a new table "Table3".
"Table3" has exactly the same columns as "Table1", but without the second insert into value into "Table2".
"Table1" already contains old data, but only the new data inserted in "Table1" should be inserted in "Table3".
-- insert new rows in History
INSERT INTO "table1"
([icao24], [callsign])
SELECT
CurInserts.icao24
,CurInserts.[callsign]
FROM
(
-- INSERT new rows FROM temptable IN currenttable
INSERT INTO "table2"
([icao24], [callsign])
OUTPUT
inserted.[icao24]
,inserted.[callsign]
SELECT
T.[icao24]
,T.[callsign]
FROM #TempTable T
LEFT JOIN "table2" Cur
ON T.[icao24] = Cur.[icao24]
WHERE Cur.[icao24] IS NULL
) CurInserts;
You could first insert the inserted into another table variable or a temporary table.
Then insert into the 2 other tables from the table variable.
Demonstration
declare #tmp table (icao24 int, callsign int);
declare #ins table (icao24 int, callsign int);
insert into #tmp (icao24, callsign) values (1,10),(2,20),(3,30);
insert into #ins (icao24, callsign)
select icao24, callsign
from
(
insert into table1 (icao24, callsign)
output inserted.icao24, inserted.callsign
select tmp.icao24, tmp.callsign
from #tmp tmp
left join table1 t on t.icao24 = tmp.icao24
where t.icao24 is null
) q;
insert into table2 (icao24, callsign)
select icao24, callsign
from #ins;
insert into table3 (icao24, callsign)
select icao24, callsign
from #ins;
select * from table1;
select * from table2;
select * from table3;
icao24 | callsign
-----: | -------:
1 | 10
2 | 20
3 | 30
icao24 | callsign
-----: | -------:
1 | 10
2 | 20
3 | 30
icao24 | callsign
-----: | -------:
2 | 20
3 | 30
Demo on db<>fiddle here

Create an SQL query from two tables in postgresql

I have two tables as shown in the image. I want to create a SQL query in postgresql to get the pkey and minimum count for each unique 'pkey' in table 1 where 'name1' is not present in the array of column 'name' in table 2.
'name' is a array
You can use ANY to check if one element exists in your name's array.
create table t1 (pkey int, cnt int);
create table t2 (pkey int, name text[]);
insert into t1 values (1, 11),(1, 9),(2, 14),(2, 15),(3, 21),(3,16);
insert into t2 values
(1, array['name1','name2']),
(1, array['name3','name2']),
(2, array['name4','name1']),
(2, array['name5','name2']),
(3, array['name2','name3']),
(3, array['name4','name5']);
select pkey
from t2
where 'name1' = any(name);
| pkey |
| ---: |
| 1 |
| 2 |
select t1.pkey, min(cnt) count
from t1
where not exists (select 1
from t2
where t2.pkey = t1.pkey
and 'name1' = any(name))
group by t1.pkey;
pkey | count
---: | ----:
3 | 16
dbfiddle here

conditional joining in oracle

Conditional joining statement : -
High level Description :-
Join table based on two columns if combination is not present then join on one table -
Detailed Table -
create table tab1
(tab1_col1 number not null,
tab1_col2 number null,
tab1_col3 varchar(10));
Lookup Table
create table lkp1
(lkp_col1 number not null,
lkp_col2 number not null,
lkp_col3 number not null,
lkp_col4 varchar(10));
Insert Statement -
tab1
insert into tab1 values (10,101,'A');
insert into tab1 values (12,101,'B');
insert into tab1 values (11,102,'C');
insert into tab1 values (13,103,'B');
insert into tab1 values (14,104,'C');
insert into tab1 values (15,108,'A');
insert into tab1 values (16,102,'D');
Lookup Table
lkp1
insert into lkp1 values (10,101,50,'PICK');
insert into lkp1 values (10,101,50,'PICK');
insert into lkp1 values (11,102,100,'SKIP');
insert into lkp1 values (11,110,50,'PICK');
insert into lkp1 values (13,103,40,'PICK');
insert into lkp1 values (13,103,60,'PICK');
insert into lkp1 values (14,199,100,'PICK');
insert into lkp1 values (15,115,80,'PICK');
insert into lkp1 values (15,115,20,'PICK');
Requirement was -
Join table based on tab1_col1=lkp_col1
and
tab1_col2=lkp_col2
Filter out lookup table data lkp_col4=SKIP
If record not present in lookup table for then give default value(99.99).
(All records from tab1 table should be selected).
I built this query and it was working fine.
SELECT tab1_col1, tab1_col2, NVL (lkp_col3, '99.99') "LKP_COL3"
FROM tab1,
(SELECT *
FROM lkp1
WHERE lkp_col4 = 'PICK') lkp
WHERE tab1_col1 = lkp_col1(+) AND tab1_col2 = lkp_col2(+)
Now requirement changed
First check if
tab1_col1=lkp_col1
and
tab1_col2=lkp_col2
If lookup table is not having data for this combination
then check again with
tab1_col1=lkp_col1
If this is not also available then give dafault value.
Database - Oracle 10g
What I have tried so far
After lot of trail and error I m able to get the output. However, is there a better or simple way to use this ?
SELECT tab1_col1, tab1_col2, LKP_COL3
FROM tab1,
(SELECT *
FROM lkp1
WHERE lkp_col4 = 'PICK') lkp
WHERE tab1_col1 = lkp_col1 AND tab1_col2 = lkp_col2
union all
SELECT tab1_col1, tab1_col2, LKP_COL3
FROM tab1,
(SELECT *
FROM lkp1
WHERE lkp_col4 = 'PICK') lkp
WHERE tab1_col1 = lkp_col1(+)
AND
LKP_COL1|| '-' || LKP_COL2 not in( SELECT tab1_col1|| '-' || tab1_col2
FROM tab1, lkp1 lkp
WHERE tab1_col1 = lkp_col1 AND tab1_col2 = lkp_col2)
order by 1
The following result:
| TAB1_COL1 | TAB1_COL2 | LKP_COL3 |
|-----------|-----------|----------|
| 10 | 101 | 50 |
| 11 | 102 | 50 |
| 12 | 101 | 99.99 |
| 13 | 103 | 40 |
| 13 | 103 | 60 |
| 14 | 104 | 100 |
| 15 | 108 | 20 |
| 15 | 108 | 80 |
| 16 | 102 | 99.99 |
was produced by this query:
SELECT DISTINCT
tab1.tab1_col1
, tab1.tab1_col2
, COALESCE(lkp1.lkp_col3, lkp2.lkp_col3, 99.99) "LKP_COL3"
FROM tab1
LEFT JOIN lkp1
ON tab1.tab1_col1 = lkp1.lkp_col1
AND tab1.tab1_col2 = lkp1.lkp_col2
AND lkp1.lkp_col4 = 'PICK'
LEFT JOIN lkp1 lkp2
ON tab1.tab1_col1 = lkp2.lkp_col1
AND lkp2.lkp_col4 = 'PICK'
ORDER BY
tab1.tab1_col1
, tab1.tab1_col2
;
DISTINCT was added because the second left (outer) join produces unwanted repetition in the output.
refer to this sqlfiddle

Merge two rows in SQL

Assuming I have a table containing the following information:
FK | Field1 | Field2
=====================
3 | ABC | *NULL*
3 | *NULL* | DEF
is there a way I can perform a select on the table to get the following
FK | Field1 | Field2
=====================
3 | ABC | DEF
Thanks
Edit: Fix field2 name for clarity
Aggregate functions may help you out here. Aggregate functions ignore NULLs (at least that's true on SQL Server, Oracle, and Jet/Access), so you could use a query like this (tested on SQL Server Express 2008 R2):
SELECT
FK,
MAX(Field1) AS Field1,
MAX(Field2) AS Field2
FROM
table1
GROUP BY
FK;
I used MAX, but any aggregate which picks one value from among the GROUP BY rows should work.
Test data:
CREATE TABLE table1 (FK int, Field1 varchar(10), Field2 varchar(10));
INSERT INTO table1 VALUES (3, 'ABC', NULL);
INSERT INTO table1 VALUES (3, NULL, 'DEF');
INSERT INTO table1 VALUES (4, 'GHI', NULL);
INSERT INTO table1 VALUES (4, 'JKL', 'MNO');
INSERT INTO table1 VALUES (4, NULL, 'PQR');
Results:
FK Field1 Field2
-- ------ ------
3 ABC DEF
4 JKL PQR
There are a few ways depending on some data rules that you have not included, but here is one way using what you gave.
SELECT
t1.Field1,
t2.Field2
FROM Table1 t1
LEFT JOIN Table1 t2 ON t1.FK = t2.FK AND t2.Field1 IS NULL
Another way:
SELECT
t1.Field1,
(SELECT Field2 FROM Table2 t2 WHERE t2.FK = t1.FK AND Field1 IS NULL) AS Field2
FROM Table1 t1
There might be neater methods, but the following could be one approach:
SELECT t.fk,
(
SELECT t1.Field1
FROM `table` t1
WHERE t1.fk = t.fk AND t1.Field1 IS NOT NULL
LIMIT 1
) Field1,
(
SELECT t2.Field2
FROM `table` t2
WHERE t2.fk = t.fk AND t2.Field2 IS NOT NULL
LIMIT 1
) Field2
FROM `table` t
WHERE t.fk = 3
GROUP BY t.fk;
Test Case:
CREATE TABLE `table` (fk int, Field1 varchar(10), Field2 varchar(10));
INSERT INTO `table` VALUES (3, 'ABC', NULL);
INSERT INTO `table` VALUES (3, NULL, 'DEF');
INSERT INTO `table` VALUES (4, 'GHI', NULL);
INSERT INTO `table` VALUES (4, NULL, 'JKL');
INSERT INTO `table` VALUES (5, NULL, 'MNO');
Result:
+------+--------+--------+
| fk | Field1 | Field2 |
+------+--------+--------+
| 3 | ABC | DEF |
+------+--------+--------+
1 row in set (0.01 sec)
Running the same query without the WHERE t.fk = 3 clause, it would return the following result-set:
+------+--------+--------+
| fk | Field1 | Field2 |
+------+--------+--------+
| 3 | ABC | DEF |
| 4 | GHI | JKL |
| 5 | NULL | MNO |
+------+--------+--------+
3 rows in set (0.01 sec)
I had a similar problem. The difference was that I needed far more control over what I was returning so I ended up with an simple clear but rather long query. Here is a simplified version of it based on your example.
select main.id, Field1_Q.Field1, Field2_Q.Field2
from
(
select distinct id
from Table1
)as main
left outer join (
select id, max(Field1)
from Table1
where Field1 is not null
group by id
) as Field1_Q on main.id = Field1_Q.id
left outer join (
select id, max(Field2)
from Table1
where Field2 is not null
group by id
) as Field2_Q on main.id = Field2_Q.id
;
The trick here is that the first select 'main' selects the rows to display. Then you have one select per field. What is being joined on should be all of the same values returned by the 'main' query.
Be warned, those other queries need to return only one row per id or you will be ignoring data
if one row has value in field1 column and other rows have null value then this Query might work.
SELECT
FK,
MAX(Field1) as Field1,
MAX(Field2) as Field2
FROM
(
select FK,ISNULL(Field1,'') as Field1,ISNULL(Field2,'') as Field2 from table1
)
tbl
GROUP BY FK
My case is I have a table like this
---------------------------------------------
|company_name|company_ID|CA | WA |
---------------------------------------------
|Costco | 1 |NULL | 2 |
---------------------------------------------
|Costco | 1 |3 |Null |
---------------------------------------------
And I want it to be like below:
---------------------------------------------
|company_name|company_ID|CA | WA |
---------------------------------------------
|Costco | 1 |3 | 2 |
---------------------------------------------
Most code is almost the same:
SELECT
FK,
MAX(CA) AS CA,
MAX(WA) AS WA
FROM
table1
GROUP BY company_name,company_ID
The only difference is the group by, if you put two column names into it, you can group them in pairs.
SELECT Q.FK
,ISNULL(T1.Field1, T2.Field2) AS Field
FROM (SELECT FK FROM Table1
UNION
SELECT FK FROM Table2) AS Q
LEFT JOIN Table1 AS T1 ON T1.FK = Q.FK
LEFT JOIN Table2 AS T2 ON T2.FK = Q.FK
If there is one table, write Table1 instead of Table2