Merging two views in PostgreSQL - sql

I have two views in below format.
ProductId Version IsAvailable
123 1 Yes
124 1 No
125 1 Yes
126 1 No
ProductId Version IsShippable
123 1 Yes
124 1 Yes
125 1 No
127 1 Yes
I need to merge these two tables into a single table:
ProductId Version IsAvailable IsShippable
123 1 Yes Yes
124 1 No Yes
125 1 Yes No
126 1 No Null
127 1 Null Yes
How can I write the query to achieve this?

Use full outer join between 2 views like below:
select a.ProductId, a.Version, IsAvailable, IsShippable
from tableA a
full outer join tableB b on a.productid =b.productid and a.version=b.version

Related

Complex SQL issue in DB2

I have a table TABLE_CLIENT_BOOK which contains USER_ID and BOOK_CODE. This table shows which all books are with a particular USER_ID.
USER_ID BOOK_CODE
------------------------------
1 123
1 124
1 567
2 123
2 432
3 432
3 567
-------------------------------
I have another table TABLE_BOOK which contains details about each book.
BOOK_CODE DETAILS
----------------------------------
123 abcd
124 pqrs
432 xyzw
567 lmnop
568 efgh
----------------------------------
I want to write a query between the two tables which will spit out USER_ID and BOOK_CODE where BOOK_CODE column should have the id of all books from TABLE_BOOK which that user doesn't have. For e.g. user 1 doesn't have books 432 and 568, user 2 doesn't have 124, 567 and 568 and user 3 doesn't have 123, 124, 568.
So the result table of the query would be:
USER_ID BOOK_CODE
----------------------------
1 432
1 568
2 124
2 567
2 568
3 123
3 124
3 568
-----------------------------
This report is to advertise the books which user doesn't have.
How do I achieve this in SQL in DB2 9 ?
Thanks for reading!
Do a CROSS JOIN to get all user/book combinations. Use NOT EXISTS to exclude already existing combinations:
select distinct tcb.USER_ID, tb.BOOK_CODE
from TABLE_CLIENT_BOOK tcb
cross join TABLE_BOOK tb
where not exists (select * from TABLE_CLIENT_BOOK tcb2
where tcb2.USER_ID = tcb.USER_ID
and tcb2.BOOK_CODE = tb.BOOK_CODE)
order by tcb.USER_ID, tb.BOOK_CODE
Alternatively, EXCEPT:
select tcb.USER_ID, tb.BOOK_CODE
from TABLE_CLIENT_BOOK tcb
cross join TABLE_BOOK tb
EXCEPT
select USER_ID, BOOK_CODE
from TABLE_CLIENT_BOOK
order by tcb.USER_ID, tb.BOOK_CODE
No DISTINCT needed here. EXCEPT removes the duplicates.
Executes as:
SQL>select distinct tcb.USER_ID, tb.BOOK_CODE
SQL&from TABLE_CLIENT_BOOK tcb
SQL& cross join TABLE_BOOK tb
SQL&where not exists (select * from TABLE_CLIENT_BOOK tcb2
SQL& where tcb2.USER_ID = tcb.USER_ID
SQL& and tcb2.BOOK_CODE = tb.BOOK_CODE)
SQL&order by tcb.USER_ID, tb.BOOK_CODE;
USER_ID BOOK_CODE
=========== ===========
1 432
1 568
2 124
2 567
2 568
3 123
3 124
3 568
8 rows found
SQL>select tcb.USER_ID, tb.BOOK_CODE
SQL&from TABLE_CLIENT_BOOK tcb
SQL& cross join TABLE_BOOK tb
SQL&EXCEPT
SQL&select USER_ID, BOOK_CODE
SQL&from TABLE_CLIENT_BOOK
SQL&order by tcb.USER_ID, tb.BOOK_CODE;
USER_ID BOOK_CODE
=========== ===========
1 432
1 568
2 124
2 567
2 568
3 123
3 124
3 568
8 rows found

Update multiple rows with different values in Oracle

I am trying to update multiple rows using an inner view in oracle.
The select statement for updating this view is:
select count(distinct a.numCount) as numCount, a.accNum as accNum ,
s.unitNum as unitNum
from tableA a,tableS s where a.accNum is not null and s.fk_id=
(select id from tableD where sid=a.accNum )
group by a.accNum ,s.unitNum ;
Update statement that I am trying is below:
update
(select count(distinct a.numCount) as numCount, a.accNum as accNum ,
s.unitNum as unitNum
from tableA a,tableS s where a.accNum is not null and s.fk_id=
(select id from tableD where sid=a.accNum )
group by a.accNum ,s.unitNum ) k
set k.unitNum=k.numCount;
I am trying to update unitNum with value of numCount.
The above query is not working when used as a view.
Is there another way to update this in Oracle.
Please suggest.
Structure of the tables are as below:
TableA
accNum numCount
-----------------------
111 1
222 5
333 2
111 1
111 1
222 5
222 2
TableS
fk_id unitNum
-----------------------
123 0
768 0
734 0
TableD
ID sid
-----------------------
123 222
768 111
734 333
Output should be as below:
TableS
fk_id unitNum
-----------------------
123 3
768 3
734 1
Please suggest
update tableS s
set unitNum=
(select count(distinct a.numCount) as numCount
from tableA a, tableD d
where s.fk_id=d.id and d.sid=a.accNum
);

SQL- Add Missing data in Left outer joing query

I have following data
Components
componentid title
1 houseRent
2 medical
3 Travelling Allowance
empPayrollMaster
MasterID EmployeeID SalaryMonthID
1 101 1
2 102 1
3 103 1
empPayrollDetail
DetailID MasterID ComponentID amount
1 1 1 100
2 1 2 500
3 2 1 300
4 2 3 250
5 3 1 150
6 3 2 350
7 3 3 450
Required Output
EmployeeID MasterID ComponentID amount
101 1 1 100
101 1 2 500
101 1 3 0
102 2 1 300
102 1 2 0
102 2 3 250
103 3 1 150
103 3 2 350
103 3 3 450
To get the required output if i do left outer join between components and empPayrollDetail I get null in EmployeeID and MasterID and amount Columns. How to modify left join to get the required output
You need to do a CROSS JOIN on Components and empPayrollMaster to generate first all combination of employees and components. Then, do a LEFT JOIN on empPayrollDetail to achieve the result, using ISNULL(amount, 0) for NULL amounts.
SQL Fiddle
SELECT
epm.EmployeeID,
epm.MasterID,
c.ComponentID,
amount = ISNULL(epd.amount, 0)
FROM empPayrollMaster epm
CROSS JOIN Components c
LEFT JOIN empPayrollDetail epd
ON epd.MasterID = epm.MasterID
AND epd.ComponentID = c.ComponentID
Try this
select empPayrollMaster.EmployeeID,empPayrollMaster.MasterID,
Components.componentid,isnull(empPayrollDetail.amount,0)
from empPayrollMaster
left join Components
on empPayrollMaster.EmployeeID is not null
left join empPayrollDetail
on empPayrollDetail.MasterID = empPayrollMaster.MasterID
and empPayrollDetail.ComponentID = Components.componentid
Try this way
select c.EmployeeID,d.MasterID,c.ComponentID,isnull(d.amount,0) as amount from (
select * from Components a
Cross join empPayrollMaster b) c
left outer join empPayrollDetail d on d.componentid =c.componentid
As you want the component amount for each employee in the master table you should use a insull(payrole_detail.amount,0) or, as #Turophile pointed out, the SQL standard function coalesce(payrole_detail.amount,0) for the amounts column.
SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
INNER JOIN Orders
ON Customers.CustomerID=Orders.CustomerID
ORDER BY Customers.CustomerName;

SQL display data which is not mapped in another table

I am looking for a query to a result where I can see only userid1 data whose provider is not mapped in Table 2; Here is my table definition and data;
Table 1
userid providerid
1 101
1 104
1 106
1 107
2 102
2 103
2 104
Table 2
providerid
101
102
103
104
105
106
107
108
109
110
query required as per the o/p:-
userid providernotavailable
1 102
1 103
1 105
1 108
1 109
1 110
2 101
2 105
2 106
2 107
2 108
2 109
2 110
You can use the not in operator:
SELECT *
FROM table1
WHERE providerid NOT IN (SELECT providerid FROM table2)
Multiple versions: fist with NOT IN
SELECT table1.*
FROM table1
WHERE table1.providerId NOT IN ( SELECT table2.providerId FROM table2 )
Second with NOT EXISTS:
SELECT table1.*
FROM table1
WHERE NOT EXISTS ( SELECT 1
FROM table2
WHERE table1.providerId = table2.providerId )
This next one is a bit strange: we do a LEFT JOIN and we check that the second table hasn't matched:
SELECT table1.*
FROM table1
LEFT JOIN table2
ON table1.providerId = table2.providerId
WHERE table2.providerId IS NULL
Which of the three versions above performs better depends (mostly) on the cardinality of the two tables.
Sorry, I misunderstood the question. This should do the trick.
The first part of the query selects all the pairs userId - providerId. The second part removes all the ones present in table1.
SELECT U.userId, P.providerId
FROM (SELECT DISTINCT table1.userId FROM table1) U, table2 P
MINUS
SELECT table1.* FROM table1
EDIT
this is the table structure i have used to get the output
SQL> desc tab1
Name Null? Type
---------------------------- -------- ----------------
USERID NUMBER(38)
PROVIDERID NUMBER(38)
SQL> desc tab2
Name Null? Type
---------------------------- -------- ----------------
PROVIDERID NUMBER(38)
SQL> select distinct(a.userid),b.providerId from tab1 a, tab2 b
minus
select * from tab1 ;
USERID PROVIDERID
---------- ----------
1 102
1 103
1 105
1 108
1 109
1 110
2 101
2 105
2 106
2 107
2 108
2 109
2 110
13 rows selected.
SELECT a.userid, b.providerid FROM table1 a, table2 b
WHERE a.providerid IS NOT NULL
MINUS
SELECT userid, providerid FROM table1 a
WHERE a.providerid IS NOT NULL;
The query bring the desired output...
Thanks all for ur efforts.

SQL Server: Include Missing data in Query

I have two tables in SQL Server that looks as follows,
Table 1:
Store Type
100 A
101 B
102 B
103 B
104 C
105 C
106 A
107 A
108 D
109 D
110 C
111 B
112 D
and table 2:
Store Units
100 5
101 3
102 10
103 6
104 6
105 8
I want to combine the two tables in a query with a relationship link between the Store column of the two tables. The problem i have is that if i create a query between the two then the stores from 106 to 112 does not appear in the table. The query looks as follows,
SELECT dbo.Table1.Store,
dbo.Table1.Type,
dbo.Table2.Units
FROM Table1 INNER JOIN Table2
ON dbo.Table1.Store=dbo.Table2.Store
What should i do to include the stores that does not appear in Table2 (106-112) but in Table1 and make there Units = 0, such that the query table look as follows,
Store Type Units
100 A 5
101 B 3
102 B 10
103 B 6
104 C 6
105 C 8
106 A 0
107 A 0
108 D 0
109 D 0
110 C 0
111 B 0
112 D 0
You want a left outer join instead of an inner join:
SELECT t1.Store, t1.Type, COALESCE(t1.Units, 0) as Units
FROM Table1 t1 LEFT JOIN
Table2 t2
ON t1.Store = t2.Store;
I also introduced table aliases for your query to make it more readable. Note the use of coalesce() so you get 0 for Units instead of NULL.
SELECT dbo.Table1.Store, dbo.Table1.Type, coalesce(dbo.Table2.Units, 0) As Units
FROM Table1
LEFT JOIN Table2 ON dbo.Table1.Store=dbo.Table2.Store