Retrieve from Oracle db key value pair - oracle

I need to retrieve 3 values with different key from a key value pair table.
My database schema as follows. I need to reach to table3 from table1 by taking the E_SUBID and then joining the table2 with E_SUBID. Once table1 and table2 are joined I need take to take E_CID from table2 to join it with table2 E_CID to get the "Attr_Value" keeping E_CID as a criteria.
Table1
------------------------
|E_SUBID| B_LocationID |
|1 100 |
|2 101 |
|3 102 |
Table2
-----------------
|E_CID | E_SUBID|
|10 1 |
|11 2 |
|12 3 |
Table3
---------------------------------
|E_CID | Attr_name | Attr_Value |
|10 Product Samsung |
|10 Model Smartphone |
|10 usage daily |
|11 Product Apple |
|11 Model Ipad |
|11 usage everyday |
|12 Model smartwatch |
I have been successful to join table1,table2 and table3 but I cannot get the required output which as follows
OUTPUT
|Product | Model | Usage |
Samsung Smartphone daily
Apple Ipad everyday
null smartwatch null
The query which joins table1, table2 and table3 as follows
select distinct t3.Attr_value as Product
from table1 t1, table2 t2, table3 t3
where t1.E_SUBID = t2.E_SUBID and
t2.E_CID = t3.E_CID and
t3.Attr_name=?????
order by Product;
Thank you for your time.

In a case like this, you can join to table3 as often as you need to for each attribute name you wish to display:
select
p.attr_value product,
m.attr_value "model", -- Quotes to escape reserved word
u.attr_value usage
from table1 t1
join table2 t2 on t1.e_subid = t2.e_subid
left outer join table3 p on t2.e_cid = p.e_cid and p.attr_name = 'Product'
left outer join table3 m on t2.e_cid = m.e_cid and m.attr_name = 'Model'
left outer join table3 u on t2.e_cid = u.e_cid and u.attr_name = 'Usage'
order by 1;
Edit
Based on the comment, by making table3 optional (outer join) the query should return all rows and whether or not a Model or Usage or Product has been defined.

Try as below ... Basically you are trying to transpose the rows to column in table3.
Select Product, "Model", Usage
From
(
Select
t1.E_SUBID,
t2.E_CID,
Max(Case when T3.Attr_name = 'Product' Then T3.Attr_Value else null end) Product,
max(Case when T3.Attr_name = 'Model' Then T3.Attr_Value else null end) Model,
max(Case when T3.Attr_name = 'Usage' Then T3.Attr_Value else null end) Usage
From Table1 t1,
Table2 t2,
Table3 t3
Where
t1.E_SUBID = t2.E_SUBID
and t2.E_CID = t3.E_CID
group by t1.t1.E_SUBID,t2.E_CID
);

Related

Hive - create table by select columns from different tables

Here are my hive tables:
table1:
|a |b |c |
----------
|a1|b1|c1|
|a2|b2|c2|
|a3|b3|c3|
|a4|b4|c4|
|a5|b5|c5|
table2:
|x |y |z |
----------
|x1|y1|z1|
|x2|y2|z2|
|x3|y3|z3|
|x4|y4|z4|
|x5|y5|z5|
Desired output:
|a |b |x |y |
-------------
|a1|b1|x1|y1|
|a2|b2|x2|y2|
|a3|b3|x3|y3|
|a4|b4|x4|y4|
|a5|b5|x5|y5|
is it really possible in hive? Any help would be appreciated, Thank you!
You seem to want to "line up" the rows of both tables. Assuming that column a can be used to order the record in table1 (resp column x in table2), you can use row_number() as follows:
select t1.a, t1.b, t2.x, t2.y
from (select t1.*, row_number() over(order by a) rn from table1 t1) t1
inner join (select t2.*, row_number() over(order by x) rn from table2 t2) t2
on t1.rn = t2.rn
If the tables may have a different number of rows, and you want to retain "additional" rows, you can just change the inner join to a full join.

oracle, join with special requests

I have three tables with articles, inventory and warehouse.
CREATE TABLE "ARTICLE"
( "ID" NUMBER(9,0),
"NAME" VARCHAR2(30 BYTE)
)
CREATE TABLE "INVENTORY"
( "ID" NUMBER(9,0),
"ARTICLE_ID" NUMBER(9,0),
"QUANTITY" NUMBER(9,0),
"WAREHOUSE_ID" NUMBER(9,0)
)
CREATE TABLE "WAREHOUSE"
( "ID" NUMBER(9,0),
"NAME" VARCHAR2(30 BYTE)
)
I created a view, with shows me all inventory (with article name, etc.)
CREATE VIEW "INVENTORY_VIEW" AS
a.ID AS A_ID,
a.NAME AS A_NAME,
i.ID AS I_ID,
i.QUANTITY AS I_QUANTITY,
i.WAREHOUSE_ID AS I_WAREHOUSE_ID
FROM
ARTICLE a
LEFT OUTER JOIN INVENTORY i ON i.ARTICLE_ID = a.ID
I did it to make sure, I get a row for each article, even if there's no row in inventory. (I_WAREHOUSE_ID is null in that special case)
This works fine except for one case:
As soon as there is one row in INVENTORY for another warehouse of course the row (with I_WAREHOUSE_ID = null) disapears for the other warehouses.
(The other warehouses (e.g. Warehouse 2) select the inventory by "WHERE I_WAREHOUSE_ID=2" or "I_WAREHOUSE_ID is null".)
Anybody an idea how to solve this?
What I need is a article row for each WAREHOUSE_ID (with ID) if there is no iventory row for this article and warehouse.
My idea was to create a second view with all article / warehouse combinations and then kind of join that table with the inventory, but I had no success.
If I understand you correctly, you want one result row per article and warehouse. So cross join the two tables and outer join the inventory then:
CREATE VIEW inventory_view AS
SELECT
a.id AS article_id,
a.name AS article_name,
i.id AS inventory_id,
i.quantity AS inventory_quantity,
w.id AS warehouse_id
FROM ARTICLE a
CORSS JOIN WAREHOUSE w
LEFT OUTER JOIN inventory i ON i.article_id = a.id AND i.warehouse_id = w.id;
If I understand correctly what you asked (pls next time post expected result in tabular text) you could try following query:
SELECT
A.ID AS A_ID,
A.NAME AS A_NAME,
I.ID AS I_ID,
I.QUANTITY AS I_QUANTITY,
I.WAREHOUSE_ID AS I_WAREHOUSE_ID
, W2.NAME
, W2.ID
FROM ARTICLE A
LEFT JOIN INVENTORY I ON I.ARTICLE_ID = A.ID
CROSS JOIN WAREHOUSE W2
WHERE I.WAREHOUSE_ID IS NULL OR (W2.ID IS NOT NULL AND I.WAREHOUSE_ID=W2.ID);
Sample data:
INSERT INTO ARTICLE VALUES (1,'PROD_A');
INSERT INTO ARTICLE VALUES (2,'PROD_B');
INSERT INTO INVENTORY VALUES (1, 1,10,2);
INSERT INTO "WAREHOUSE" VALUES (1,'WA');
INSERT INTO "WAREHOUSE" VALUES (2,'WB');
Output:
+------+--------+------+------------+----------------+------+----+
| A_ID | A_NAME | I_ID | I_QUANTITY | I_WAREHOUSE_ID | NAME | ID |
+------+--------+------+------------+----------------+------+----+
| 1 | PROD_A | 1 | 10 | 2 | WB | 2 |
| 2 | PROD_B | NULL | NULL | NULL | WA | 1 |
| 2 | PROD_B | NULL | NULL | NULL | WB | 2 |
+------+--------+------+------------+----------------+------+----+

Complex SQL query to join two tables

Problem:
Given two tables: TableA, TableB, where TableA has a one-to-many relationship with TableB, I want to retrieve all records in TableB for where the search criteria matches a certain column in TableB and return NULL for the unique TableA records for the same attribute.
Table Structures:
Table A
ID(Primary Key) | Name | City
1 | ABX | San Francisco
2 | ASDF | Oakland
3 | FDFD | New York
4 | GFGF | Austin
5 | GFFFF | San Francisco
Table B
ATTR_ID |Attr_Type | Attr_Name | Attr_Value
1 | TableA | Attr_1 | Attr_Value_1
2 | TableD | Attr_1 | Attr_Value_2
1 | TableA | Attr_2 | Attr_Value_3
3 | TableA | Attr_4 | Attr_Value_4
9 | TableC | Attr_2 | Attr_Value_5
Table B holds attribtue names and values and is a common table used across multiple tables. Each table is identified by Attr_Type and ATTR_ID (which maps to the IDs of different tables).
For instance, the record in Table A with ID 1 has two attributes in Table B with Attr_Names: Attr_1 and Attr_2 and so on.
Expected Output
ID | Name | City | TableB.Attr_Value
1 | ABX | San Francisco | Attr_Value_1
2 | ASDF | Oakland | Attr_Value_2
3 | FDFD | New York | NULL
4 | GFGF | Austin | NULL
5 | GFFFF | San Francisco | NULL
Search Criteria:
Get rows from Table B for each record in Table A with ATTR_NAME Attr_1. If a particular TableA record doesn't have Attr_1, return null.
My Query
select id, name, city,
b.attr_value from table_A
join table_B b on
table_A.id =b.attr_id and b.attr_name='Attr_1'
This is a strange data structure. You need a left outer join with the conditions in the on clause:
select a.id, a.name, a.city, b.attr_value
from table_A a left join
table_B b
on a.id = b.attr_id and b.attr_name = 'Attr_1' and b.attr_type = 'TableA';
I added the attr_type condition, because that seems logic with this data structure.
I dont have an sql server to test the command, but what you want is an inner/outer join query. You could do something like this
select id, name, city,
b.attr_value from table_A
join table_B b on
table_A.id *= b.attr_id and b.attr_name *= 'Attr_1'
Something like this should do the trick for you

Oracle update with subquery - performanceissue

I'm having some trouble with an update statement in my oracle database.
The query takes to much time and the temp tablespace is running out of space, but it provides the correct data.
I tried to convert the subqueries to joins but i couldn't figure out how to do it correctly.
If someone knows how to improve the statement or how to convert it into a join i would be really grateful.
UPDATE table1 t1
SET t1.inxdc = (SELECT sda_x
FROM table2 t2
WHERE t1.c1 = t2.c1
AND t1.c2 = t2.c2
AND t1.c3 = t2.c3
AND t1.c4 = t2.c4
AND t1.c5 = t2.c5
AND t1.c6 = t2.c6
AND t2.ident = 'K_SDA_W'
AND rownum=1)
WHERE EXISTS
(SELECT 1
FROM table2 t2
WHERE t1.c1 = t2.c1
AND t1.c2 = t2.c2
AND t1.c3 = t2.c3
AND t1.c4 = t2.c4
AND t1.c5 = t2.c5
AND t1.c6 = t2.c6
AND t2.ident = 'K_SDA_W');
edit1:
Some information for the tables
table1 PKs = c1,c2,c3,c4,c5,c6
table2 PKs = ident,c4,c5,c6, and 3 others not mentioned in the statement (c7,c8,c9)
index: besides the PKs only on table2 c1
table1 data: 12466 rows
table2 data: 194827 rows
edit2:
Execution Plan
--------------------------------------------------------------
| Id | Operation | Name |
--------------------------------------------------------------
| 0 | UPDATE STATEMENT | |
| 1 | UPDATE | table1 |
| 2 | NESTED LOOPS SEMI | |
| 3 | TABLE ACCESS FULL | table1 |
| 4 | TABLE ACCESS BY INDEX ROWID| table2 |
| 5 | INDEX RANGE SCAN | t2.c1 |
| 6 | COUNT STOPKEY | |
| 7 | TABLE ACCESS BY INDEX ROWID| table2 |
| 8 | INDEX RANGE SCAN | t2.PK |
--------------------------------------------------------------
There are very few rows in Table1, just drop the WHERE clause in this particular situation and add NVL to the value returned from subquery:
UPDATE table1 t1
SET t1.inxdc = NVL((SELECT sda_x
FROM table2 t2
WHERE t1.c1 = t2.c1
AND t1.c2 = t2.c2
AND t1.c3 = t2.c3
AND t1.c4 = t2.c4
AND t1.c5 = t2.c5
AND t1.c6 = t2.c6
AND t2.ident = 'K_SDA_W'
AND rownum=1), t1.inxdc);
In general your update should be quick, have you checked performance of the subquery? Check if an index (and which one) is used on table2 for the subquery (best, show us the exection plan).
I think table t2 shoulkd have an index on c1,c2,c3, c4,c5,c6,ident
In this case the update of t1 should be really faster.

Update query Oracle

I have table TB1 which has the following cols:
ID | date
---------------------
1 | 12-JUL-10
2 | 12-JUL-10
3 | 12-JUL-10
4 | 12-JUL-10
.
.
.
10000 | 12-JUL-10
table2
ID | date
---------------------
1 | 12-JAN-09
2 | 12-JUL-09
3 | 12-JUL-09
4 | 12-JUL-08
.
.
.
5800 | 12-JUL-08
How to update the table2's date which has similar ID as table1.
Thanks :)
In general
UPDATE table2 t2
SET date_col = (SELECT t1.date_col
FROM table1 t1
WHERE t1.id = t2.id)
WHERE EXISTS (
SELECT 1
FROM table1 t1
WHERE t1.id = t2.id )
If you can be guaranteed that every ID in table2 exists in table1 (or if you want the date_col set to NULL if there is no match), you can eliminate the WHERE EXISTS. But generally you only want to do an update if there is a matching record.
Then there is also using an inline view for the update. This is slightly trickier to get right because I think it requires a primary key to exist on both sides of the join otherwise it fails with an error.
update (
select
t1.id as t1_id,
t1.value as t1_date,
t2.id as t2_id,
t2.value as t2_date
from
table1 t1
join table2 t2 on (t1.id = t2.id)
)
set t2_date = t1_date

Resources