Create view from 3 tables - sql

I have 3 tables.
table1
id info1 info2
1 a b
2 a b
3 a b
4 a b
table2
id table1_id column_id value
1 1 1 10
2 1 2 20
3 1 3 30
4 2 1 40
5 2 2 50
6 2 3 60
7 3 1 70
8 3 2 80
9 3 3 90
10 4 1 100
11 4 2 110
12 4 3 120
table3
column_id column
1 column1
2 column2
3 column3
Based on the above, I need to create a view which would convert rows to columns in the following way:
column1 column2 column3
10 20 30
40 50 60
70 80 90
100 110 120
Is it possible to create a view like the above?

You can use below if you use oracle 11g or above you can use pivot also.
SELECT max(CASE
WHEN column1 = 'column1'
THEN value1
END) column1
,max(CASE
WHEN column1 = 'column2'
THEN value1
END) column2
,max(CASE
WHEN column1 = 'column3'
THEN value1
END) column3
FROM (
SELECT t2.table1_id
,t3.column1
,to_char(t2.value1) AS value1
FROM table2 t2
JOIN table1 t1 ON t1.id1 = t2.table1_id
JOIN table3 t3 ON t3.column_id = t2.column_id
)
GROUP BY table1_id

The short answer to the question is yes, a solution to the problem could be to join the tables and then pivot them.
I have written some code as a suggestion to help you along, this is untested code and you will have to tweak it a bit
select * from (
select T1.id as Row, T3.column, T2.value
from table1 T1
left join table2 T2 on T2.table1_id = T1.id
left join table3 T3 on T3.column_id = T2.column_id
)
pivot
(
sum(value)
for value in ('column1','column2','column3')
)
group by row
order by row

Related

Deleting a range of rows from a table based on another table as input in SQL

I'm using SQL Server. I need help to remove a range of rows from Table1 using input values and matching Ids from Table2.
Table1
RowId
SetId
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
1
1
2
2
2
3
2
4
2
Table2
StartId
EndId
SetId
2
3
1
6
8
1
1
2
2
Result Table
RowId
SetId
1
1
4
1
5
1
9
1
3
2
4
2
So far this is the non-working code I have. I want to Delete RowId's from Table1 where they are greater than or equal to and less than or equal to the StartId and EndId of Table2 and having matching SetId's from Table1.
Delete From Table1
Where RowId >=
(Select StartId From Table2 Where Table1.SetId = Table2.SetId)
and RowId <=
(Select EndId From Table2 Where Table1.SetId = Table2.SetId)
you can use not exists:
select * from table1 t1
where not exists (
select 1
from table2 t2
where t1.RowId between t2.StartId and t2.EndId
and t1.setid = t2.setid
)
and if you want to delete those rows:
delete from table1 t1
where exists (
select 1
from table2 t2
where t1.RowId between t2.StartId and t2.EndId
and t1.setid = t2.setid
)

How to find records which ALL values in column are contained in another table?

I have such tables:
Table1
ID | Name
---------
1 Name1
2 Name2
3 Name3
Table2
ID | FindID Table1ID
--------------------
1 1 1
2 2 1
3 1 2
4 2 2
5 1 3
6 2 3
7 3 3
8 1 4
Table3
ID
--
1
2
What I need to do - I need to find all Table 1 Ids which have in Table 2 all Table 3 values as FindId column's values .
For example, if in Table 3 we have 1 and 2, in result it should return
Result
ID
-----
1
2
3
Because Table1.Id = 1 have 1 and 2 in Table 2, same for Table1.Id = 2, and Table1.Id = 3 have 1,2,3.
Table1.Id = 4 has only 1, so it isn't contained in results.
If in Table 3 we have 1,2,3 - then only Table1.Id = 3 will be returned.
I've tried something like
SELECT distinct t1.id FROM Table1 t1
join Table2 t2 on t2.Table1Id = t1.ID
join Table3 t3 on t3.Id = t2.FindId
But it doesn't work.
If I understand correctly, you want all table2.table1id that have all the findIds in table3. If so, aggregation should do what you want:
select t2.table1id
from table2 t2 join
table1 t3
on t2.findid = t3.id
group by t2.table1id
having count(*) = (select count(*) from table3);

require to form a sql query

I was working on preparing a query where I was stuck.
Consider tables below:
table1
id key col1
-- --- -----
1 1 abc
2 2 d
3 3 s
4 4 xyz
table2
id col1 foreignkey
-- ---- ----------
1 12 1
2 13 1
3 14 1
4 12 2
5 13 2
Now what I need is to select only those records from table1 for which the corresponding entries in table2 does not have say col1 value as 12.
So the challenge is after applying join even though it will skip for value 1 corresponding to col1 equal to 12 it still has another multiple rows whose values are say 13, 14 for which also they have same foreignkey. Now what I want is if there is a single row having value 12 then it should not pick that id at all from table1.
How can I form a query with this?
The output which i need is say from above table structure i want to get those records from table1 for which col1 value from table2 does not have value as 14.
so my query should return me only row 2 from table1 and not row 1.
Another way of doing that. The first two queries are just for making the sample data.
;WITH t1(id ,[key] ,col1) AS
(
SELECT 1 , 1 , 'abc' UNION ALL
SELECT 2 , 2 , 'd' UNION ALL
SELECT 3 , 3 , 's' UNION ALL
SELECT 4 , 4 , 'xyz'
)
,t2(id ,col1, foreignkey) AS
(
SELECT 1 , 12 , 1 UNION ALL
SELECT 2 , 13 , 1 UNION ALL
SELECT 3 , 14 , 1 UNION ALL
SELECT 4 ,12 , 2 UNION ALL
SELECT 5 ,13 , 2
)
SELECT id, [key], col1
FROM t1
WHERE id NOT IN (SELECT t2.Id
FROM t2
INNER JOIN t1 ON t1.Id = t2.foreignkey
WHERE t2.col1 = 14)
This is a typical case for NOT EXISTS:
SELECT id, [key], col1
FROM table1 t1
WHERE NOT EXISTS (SELECT 1
FROM table2 t2
WHERE t2.foreignkey = t1.id AND t2.col1 = 14)
The above query will not select a row from table1 if there is a single correlated row in table2 having col1 = 14.
Output:
id key col1
-------------
2 2 d
3 3 s
4 4 xyz
If you want to return records that, in addition to the criterion set above, also have correlated records in table2, then you can use the following query:
SELECT t1.id, MAX(t1.[key]) AS [key], MAX(t1.col1) AS col1
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.foreignkey
GROUP BY t1.id
HAVING COUNT(CASE WHEN t2.col1 = 14 THEN 1 END) = 0
Output:
id key col1
-------------
2 2 d
You can also achieve the same result with the second query using a combination of EXISTS and NOT EXISTS:
SELECT id, [key], col1
FROM table1 t1
WHERE EXISTS (SELECT 1
FROM table2 t2
WHERE t2.foreignkey = t1.id)
AND
NOT EXISTS (SELECT 1
FROM table2 t3
WHERE t3.foreignkey = t1.id AND t3.col1 = 14)
select t1.id,t1.key,
(select ROW_NUMBER() OVER(PARTITION BY col1 ORDER BY col1 DESC) AS Row,* into
#Temp from table1)
from table1 t1
inner join table2 t2 on t1.id=t2.foreignkey
where t2.col1=(select col1 from #temp where row>1)

Resolved: Query that returns the output where one column matches all the values in another column

Using oracle developer, I've run a query that results in the following table. But I only want the results where column1 matches all the values columns 2 (3,4,8). So the output would be 2, 3, but not 4. I'm sure there is a way to bring this result about without hard coding it? I'm thinking its some sort of self-join?
select column1, column2
from table1
where column1 in (
select column1
from table2
where depth >= 100)
order by column2;
Output:
column1 column2
3 2
8 2
4 2
3 3
4 3
8 3
4 4
Table2
Column1 Area_Name Depth
1 Lake 40
2 River 50
3 Ocean 150
4 Cliff 150
5 Mountain 90
6 Construction 60
7 Building 50
8 Random 100
9 Also Random 50
10 Another one 80
Needed output:
column2
2
3
Ok, this is what I was looking for:
SELECT table1.column1
FROM table1
INNER JOIN table2
ON table1.column2 = table2.column2
WHERE table2.depth >= 100
GROUP BY boat_id
HAVING COUNT(*) >= (
select count(*)
from table2
where depth >= 100);
UPDATED
WITH qry AS (
SELECT column1, column2
FROM table1
WHERE column1 IN (
SELECT column1
FROM table2
WHERE depth >= 100)
)
SELECT t1.column2
FROM qry t1 LEFT JOIN qry t2
ON t1.column1 = t2.column1 AND t1.column2 = t2.column2
GROUP BY t1.column2
HAVING COUNT(*) = (SELECT COUNT(DISTINCT column1) FROM qry)
ORDER BY t1.column2
Output:
| COLUMN2 |
-----------
| 2 |
| 3 |
SQLFiddle

Joining two tables in a select

I have two tables:
TABLE 1
ID VALUE
1 ABC
2 DEF
3 GHI
4 JKL
5 XYZ
TABLE 2
ID T1_ID VALUE
1 1 A
2 1 B
3 2 A
4 3 A
5 3 B
6 4 B
I want to select all rows from TABLE 1 which have a TABLE 2 row for Values A AND B.
This would be rows 1 and 3 (not 2 because it has only A, not 4 because it has only B).
Can I do this without a subquery?
(Note: I also need to query against values in table 1 so I can't just query table 2.)
Tadaaah! Without a subquery.
select distinct
t1.*
from
Table1 t1
inner join Table2 t2a on t2a.t1_ID = t1.ID and t2a.VALUE = 'A'
inner join Table2 t2b on t2b.t1_ID = t1.ID and t2b.VALUE = 'B'
SELECT t1.ID,
t1.VALUE
FROM Table1 t1
JOIN Table2 t2
ON t1.ID = t2.T1_ID
WHERE t2.VALUE IN ( 'A', 'B' )
GROUP BY t1.ID,
t1.VALUE
HAVING COUNT(DISTINCT t2.VALUE) = 2