Get column name from one table by id in another table - sql

I have 2 tables
Table 1:
Query_code | Item_code | Column_Name
2 | 1 | CN1
2 | 2 | CN2
2 | 3 | CN3
Table 2:
Query_code | Source_item| dest_item | pair_code
2 | 1 | 2 | 1
2 | 2 | 3 | 2
What i want to achive is to get source_item-dest_item as result.
According to data that will be:
CN1-CN2
CN2-CN3
What i tried is:
SELECT A.Column_Name
FROM TABLE1 A inner join
TABLE2 B
ON A.QUERY_CODE=B.QUERY_CODE
But this is not even close to my goal

What you need to do is use TABLE2 to identify the source_item and dest_item, then join with TABLE1 the first time to replace source_item with the column name, and join again with TABLE1 to replace dest_item with the other column name.
SELECT A.Column_Name, B.Column_Name
FROM t2 C
LEFT JOIN t1 A
ON C.Source_item=A.Item_code
LEFT JOIN t1 B
ON C.Dest_item=B.Item_code
WHERE C.Query_code=A.Query_code
AND C.Query_code=B.Query_code
Running Example on SQLFiddle

This should work. It is unclear what your Query_Code is meant to do, so I omitted it from the query.
EDIT Inserted Query_code condition as well.
SELECT
Source.Column_Name || '-' || Dest.Column_Name AS ResultPair
FROM
TABLE2 B
INNER JOIN TABLE1 Source
ON B.source_item = Source.item_code AND B.Query_code = Source.Query_code
INNER JOIN TABLE1 Dest
ON B.dest_item = Dest.item_code AND B.Query_code = Dest.Query_code;

Here you go
WITH table1 (query_code, item_code ,column_name ) AS
(SELECT 2,1,'cn1' UNION ALL
SELECT 2,2,'cn2' UNION ALL
SELECT 2,3,'cn3'),
table2 (query_code , source_item, dest_item , pair_code) AS
(SELECT 2,1,2,1 UNION ALL
SELECT 2,2,3,2)
SELECT a.column_name || '-' || c.column_name
FROM table1 a
INNER JOIN table2 b ON a.item_code=b.source_item
INNER JOIN table1 c ON c.item_code=b.dest_item;

Related

How to create a table with multiple calculations?

If I do one calculation with one join:
SELECT
SUM(friends_made) as calc1, table2.group_id
FROM
friends_made_table as table1
INNER JOIN
grouped_users as table2 ON table1.user_id = table2.user_id
GROUP BY
table2.group_id
The result I get is:
calc1 | group_id
-----------------
400 | 1
320 | 2
330 | 3
But I also need another calculation (calc2) with the same inner join on table1 but with a different table (table3)
SELECT
SUM(request_accept) AS calc2, table1.group_id
FROM
friends_accept_table AS table3
INNER JOIN
grouped_users as table1 ON table1.user_id = table3.user_id
GROUP BY
table1.group_id
Result is:
calc2 | group_id
-----------------
100 | 1
150 | 2
120 | 3
How can I join these two queries and create a new table showing both of the calculations (calc1, calc2)?
calc1 |calc2 | group_id
-----------------------
400 | 100 | 1
320 | 150. | 2
330 | 120. | 3
EDITED to show tables/results and take out rounding
A join will suffice as long as there is a common set of group_ids across the two results. You may otherwise need a left/right join or full join.
with data1 as (
SELECT SUM(friends_made) as calc1, table2.group_id
FROM friends_made_table as table1 INNER JOIN grouped_users as table2
ON table1.user_id = table2.user_id
GROUP BY table2.group_id
), data2 as (
SELECT SUM(request_accept) as calc2, table1.group_id
FROM friends_accept_table as table3 INNER JOIN grouped_users as table1
ON table1.user_id = table3.user_id
GROUP BY table1.group_id
)
select calc1, calc2, d1.group_id
from data1 d1 inner join data2 d2 on d2.group_id = d1.group_id;
This does assume that your platform supports CTE syntax. If it doesn't there are probably similar rewrites.

Join tables with same keys, second table has multiple values for key and rows of second table must have same column value

I have two tables with shared key and I'm trying to join them to filter data based on few conditions
tbl1
id | OutPutValue |
1 | 2019 |
2 | 2018 |
tbl2
object_id | status | type |
1 | 22 | a |
1 | 22 | c |
1 | 33 | b |
2 | 33 | c |
2 | 33 | c |
2 | 33 | c |
What I'm trying to get is : it must select all 'OutPutValue' from tbl1 where, in tbl2 column 'type' should be c, and column 'status' must have same value for all rows i.e. 33. Note that Primary key (id) of tbl1 is foreign key (object_id) in tbl2.
Select column from tbl1 if, All rows in tbl2 (id of tbl1 have multiple rows (based on object_id) in tbl2) have same status value i.e. 33 and Type should be 'c'.
OutPutValue | Type | status |
2018 | c | 33 |
I have tried with following solution, but it's not returning desired output :
SELECT a.OutPutValue FROM tbl1 a JOIN tbl2 b ON a.id = b.object_id WHERE b.Type =c
GROUP BY a.OutPutValue, b.status HAVING b.STATUS IN(33)
You can try using correlated subquery
DEMO
select distinct OutPutValue,type, status
from t2 a inner join t1 b on a.object_id=b.id
where type='c' and not exists
(select 1 from t2 a1 where a.object_id=a1.object_id and status<>33 and type='c')
OUTPUT:
OutPutValue type status
2018 c 33
Another solution could be the following :
SELECT T1.id, T1.outputvalue FROM tbl1 T1
JOIN (
SELECT tbl2.*, MAX(type), MAX(status)
FROM tbl2
GROUP BY object_id
HAVING
MIN(status) = MAX(status) AND
MIN(type) = MAX(type)
) T2 ON T1.id = T2.object_id
WHERE T2.type = 'c'
EDIT: I have updated my query to match a particular case which make it quite similar to another answer.
FIND A DEMO HERE
Try a join combined with an aggregation:
SELECT
t1.OutPutValue,
MAX(t2.type) AS type,
MAX(t2.status) AS status
FROM tbl1 t1
INNER JOIN tbl2 t2
ON t1.id = t2.object_id
GROUP BY
t1.id,
t1.OutPutValue
HAVING
MIN(t2.status) = MAX(t2.status) AND
MAX(t2.status) = 33 AND
MIN(t2.type) = MAX(t2.type) AND
MAX(t2.type) = 'c';

Select Minus with fixed column in Oracle sql

I'd like to do a MINUS operation between two tables like these:
table1:
employee_id | job | sector
----------- | ------ | ------
10 | a | 1
10 | a | 2
10 | b | 4
table2:
job | sector
---- | ------
a | 1
a | 2
a | 3
b | 1
b | 4
c | 1
c | 2
and as result I want, for every employee_id, the {job,sector} not connected in table1.
RESULT:
employee_id | job | sector
----------- | --- | ------
10 | a | 3
10 | b | 1
10 | c | 1
10 | c | 2
Is it possible?
I hope I have written in a clear way! Thanks!
First select the complete data set, i.e. employee_id X job/sector. From these remove the existing table1 entries to get the lacking ones. (I've renamed your table table2 to job_sector for readability. I also suppose you have an employee table.)
select e.employee_id, js.job, js.sector
from employee e
cross join job_sector js
minus
select employee_id, job, sector
from table1;
Left join, where t2 is null
select t1.*
from table1 t1
let join table2 t2
on t1.job = t2.job
and t1.sector = t2.sector
where t2.job is null
This sounds like just a left join (or not in or not exists):
select 10 as employee_id, t2.*
from table2 t2 left join
table1 t1
on t2.job = t1.job and t2.sector = t1.sector
where t1.job is null;
I am a bit confused on how you get the employee id if the tables are not linked.
If you have multiple employees in t1, then you can do:
select e.employee_id, t2.*
from (select distinct employee_id from t1) e cross join
table2 t2 left join
table1 t1
on t2.job = t1.job and t2.sector = t1.sector and
e.employee_id = t1.employee_id
where t1.job is null;
You can simply achieve it by doing a left join. You query will look something like this:
SELECT T2.*
FROM TABLE2 T2 LEFT JOIN
TABLE1 T1
ON T2.JOB = T1.JOB AND T2.SECTOR = T2.SECTOR
WHERE T1.JOB IS NULL;
Though table must be linked in order to get the employee id.

How do show a result table from two 'select'? SQL

I have 2 queries:
First query:
select TableB.name, count(TableB.name) from TableB group by TableB.name
result:
name | count
Jack | 2
Marry| 1
and
Second query:
select DISTINCT TableA.kName, TableA.Value from TableA inner join TableB
ON
TableA.kName=TableB.name
result:
kName | Value
Jack | 1
Marry | 3
But I need result table:
kName | Value | newColumn
Jack | 1 | 2
Marry | 3 | 1
where the newColumn is result of first query, How can to do it? help, please.
maybe:
select DISTINCT TableA.kName, TableA.value,
(select TableB.name, count(TableB.name) from TableB group by TableB.name)
AS
newColumn from TableA inner join TableB ON TableA.kName=TableB.name
but this is not work :(
Try this query
SELECT tableB.name, tableA.value, count(tableB.name) as newColum FROM tableB
JOIN tableA ON tableB.name = tableA.kname
GROUP BY tableB.name,tableA.value
select kname, value, "newColumn"
from
(
select name, count(name) as "newColumn"
from tb
group by name
) tb
inner join
(
select distinct kname, value
from ta
) ta ta.kname = tb.name

how to combine a single column of 2 tables while selecting the other columns separately

I have 2 queries like :
select id, count(something) selected from table1...;
select id, count(something) rejected from table2...;
The first query gives me
id selected
------------
2 4
3 5
The second query gives me
id rejected
------------
1 12
3 13
I wish to combine them into the following form through a single query
id selected rejected
--------------------
1 null 12
2 4 null
3 5 13
How can I achieve this ?
You need to simulate SQL Server's FULL OUTER JOIN by combining the UNIONed results of LEFT and RIGHT joins (but in my case both are LEFT JOIN as I used to to this)
SELECT a.ID, a.selected, b.rejected
FROM (selectedQuery) a
LEFT JOIN (rejectedQuery) b
ON a.ID = b.ID
UNION
SELECT a.ID, b.selected, a.rejected
FROM (rejectedQuery) a
LEFT JOIN (selectedQuery) b
ON a.ID = b.ID
SQLFiddle Demo
UPDATE 1
PostgreSQL Supports FULL OUTER JOIN (my bad)
SELECT COALESCE(a.ID,b.id) ID, a.selected, b.rejected
FROM selectedQuery a
FULL OUTER JOIN rejectedQuery b
ON a.ID = b.ID
SQLFiddle Demo
Given some expressions that return your data:
select
column1 id,
column2 selected
from (values (2 , 4),(3, 5)) table1;
id | selected
----+----------
2 | 4
3 | 5
(2 rows)
select
column1 id,
column2 rejected
from (values (1 , 12),(3, 13)) table2
dbornside-# ;
id | rejected
----+----------
1 | 12
3 | 13
(2 rows)
The usual inner join does not produce the correct results; only rows in both relations are shown
select * from
(select column1 id, column2 selected from (values (2 , 4),(3, 5)) table1) table1
join (select column1 id, column2 rejected from (values (1 , 12),(3, 13)) table2) table2
on table1.id = table2.id;
id | selected | id | rejected
----+----------+----+----------
3 | 5 | 3 | 13
(1 row)
To get all of the rows from the right table, you need a right outer join, rows from the left is a left outer join; to get both you use a full outer join:
select *
from (select column1 id, column2 selected from (values (2 , 4),(3, 5)) table1) table1
FULL OUTER JOIN ( select column1 id, column2 rejected from (values (1 , 12),(3, 13)) table2) table2
on table1.id = table2.id;
id | selected | id | rejected
----+----------+----+----------
2 | 4 | |
3 | 5 | 3 | 13
| | 1 | 12
(3 rows)
This looks a little odd, though. that's because table1.id is not the same column as table2.id; and certain values are just not present in both tables. We can gather them together in the same step with a coalesce():
select COALESCE(table1.id, table2.id) id,
selected,
rejected
from (select column1 id, column2 selected from (values (2 , 4),(3, 5)) table1) table1
full outer join ( select column1 id, column2 rejected from (values (1 , 12),(3, 13)) table2) table2
on table1.id = table2.id;
id | selected | rejected
----+----------+----------
2 | 4 |
3 | 5 | 13
1 | | 12
(3 rows)
Could you use a JOIN in the id column? e.g.
SELECT s.id, COUNT(s.something) selected, COUNT(r.something) rejected
FROM table1 s
INNER JOIN table2 r ON r.id = s.id