Oracle SQL Out put two table at a query - sql

CREATE TABLE Products (
ID int,
name VARCHAR(70),
price NUMBER(8,2),
primary key (ID, name)
);
drop table Instock;
/* Delete the tables if they already exist */
create table Instock (
ID int,
quantity int
);
I have two table in my database. i want to have two table showing a output as a table that look like this
ID Name Price Quantity

SELECT A.ID,A.NAME,A.PRICE,B.QUANTITY FROM Products A,Instock B WHERE A.ID=B.ID

You can try this to create the new table(this creates the table in addition to putting the data in there)
CREATE TABLE MY_TABLE as SELECT A.ID,A.NAME,A.PRICE,B.QUANTITY FROM Products A,Instock B WHERE A.ID=B.ID

Related

How can I insert values from a nested table into another table?

I want to grab values from a nested table in one table and insert said values into another table
Here's the type for the nested table:
CREATE OR REPLACE TYPE type_val AS OBJECT
(
year DATE,
amount INTEGER
);
The nested table:
CREATE OR REPLACE TYPE nt_type_val IS
TABLE OF type_val;
Here's the table that contains the nested table:
CREATE TABLE country
(
id INTEGER NOT NULL,
name VARCHAR2(100) NOT NULL,
continent VARCHAR2(30) NOT NULL,
prod_an nt_type_val
)
NESTED TABLE prod_an STORE AS nt_prod_an;
Here's the table into which I want to insert
CREATE TABLE prod_country_ai
(
year DATE NOT NULL,
amount INTEGER NOT NULL,
country_fk INTEGER NOT NULL
)
What I want to do is I want to grab the values from prod_an in the country table for each country and store them in the prod_country_ai table, respectively, year and amount from the nested table (prod_an) into year and amount on prod_country_ai and the primary key from country into country_fk on prod_country_ai.
I have the following piece for a procedure that would do that:
DECLARE
CURSOR inner_table IS
SELECT t.* FROM country p, TABLE(p.prod_an) t
WHERE p.name = 'Portugal';
BEGIN
FOR i IN inner_table LOOP
dbms_output.put_line( i.year || i.quantity);
END LOOP;
END;
This successfully outputs the year followed by the amount but it only does so upon specification of the country name, the solution I thought of is running an "outer loop" that cycles on the country table (could be by id or by country name it doesn't change much because each value will be unique either way), and I'm guessing I can use i.year and i.quantity directly on an insert statement inside the "inner loop" to insert into prod_country_ai, but I'm not sure how I can do this, also, I think variables are treated as "local" inside a loop so how could I go about inserting the country primary key as a foreign key in the prod_country_ai table?
You don't need a procedure for this. You can do this with an INSERT ... SELECT from the countries cross joining the nested tables.
INSERT INTO prod_country_ai (year, amount, country_fk)
SELECT
p.year, p.amount, c.id
FROM
country c
CROSS JOIN TABLE(c.prod_an) p;

SQL change column type depending on other table [nvarchar to int(FK)]

I created a database a few months ago and actually, the architecture is awful. Now, I have almost 2 million records and because I didn't build the database correctly at the beginning, the requests are very long.
Below the two tables concerned:
TableA:
id (PK, int)
category (nvarchar)
date (datetime)
TableB
id (PK, int)
category (nvarchar)
I would like to change the category column to "int" and create a relationship between the tables (FK). See below:
TableA:
id (PK, int)
category (FK, int)
date (datetime)
Keys: PK_TableA, FK_TableB
I don't ask the solution but some tips to build the script to do that:
- change the column
- for each record,
look at the category > take the id > replace the category name (string) by the id(int)
Thanks for your help :)
Looking at how you named your columns I'd say that you want a new column categoryid (FK, int) instead of the category (nvarchar) in TableA.
The naive way of getting this would be to create a new column with a nullable property, populate it, set the constraint, remove the nullable property and last remove the category (varchar) column. If you cannot change the column name you need to add a few extra steps to switch out the columns.
Since you already have two million rows you are probaly better of creating a new table (TableC), populating it and swichting out TableA with TableC (drop/rename TableA, rename TableC TableA).
TableC:
id (PK, int)
categoryid (FK, int)
date (datetime)
You are usually better off making new tables and switching out the old one when dealing with tables with large amounts of rows.
Regards Martin
I think you can start from something like this.
At the end, after your checks (anyway backup your table before doing update), you can delete CATEGORY column from tableA and (if you want) rename column CATEGORY_ID.
If you want, before starting, you can do a check for later use (see at the end):
SELECT CATEGORY, COUNT(*) AS RC
FROM TABLEA
GROUP BY CATEGORY;
Sample script
CREATE TABLE TABLEA (ID INT, CATEGORY VARCHAR(20), DATE_A DATETIME);
CREATE TABLE TABLEB (ID INT, CATEGORY VARCHAR(20));
INSERT INTO TABLEA VALUES (1,'abc', GETDATE());
INSERT INTO TABLEA VALUES (2,'cde', GETDATE());
INSERT INTO TABLEA VALUES (3,'cde', GETDATE());
INSERT INTO TABLEA VALUES (4,'abc', GETDATE());
INSERT INTO TABLEA VALUES (5,'abc', GETDATE());
INSERT INTO TABLEA VALUES (6,'fgh', GETDATE());
INSERT INTO TABLEA VALUES (7,'zzz', GETDATE());
INSERT INTO TABLEB VALUES (100,'abc');
INSERT INTO TABLEB VALUES (200,'cde');
INSERT INTO TABLEB VALUES (300,'fgh');
SELECT * FROM TABLEA;
ALTER TABLE TABLEA ADD CATEGORY_ID INT;
UPDATE A SET CATEGORY_ID = B.ID
FROM TABLEA A
LEFT JOIN TABLEB B ON A.CATEGORY = B.CATEGORY;
--CREATE INDEX TABLEA_CATID ON TABLEA (CATEGORY_ID);
SELECT CATEGORY_ID, COUNT(*) AS RC
FROM TABLEA
GROUP BY CATEGORY_ID;
For semplicity, I didn't add PK (but as you know they are "necessary").
I suggest to define FK constraint on TABLEA for CATEGORY_ID.

SQL Server 2008 R2: Show only recently added records

I have two tables:
Cust : Contains customer details like customer ID and customer Name.
Cust_Address : This table contains customer ID and customer address.
Table: Cust
create table cust
(
cust_id int,
cust_name varchar(10)
);
Records Insertion:
insert into cust values(1,'A');
insert into cust values(2,'B');
insert into cust values(3,'C');
insert into cust values(4,'D');
Table: Cust_Address
create table cust_address
(
cust_id int,
cust_add varchar(50)
);
Records Insertion:
insert into cust_address values(1,'US');
insert into cust_address values(2,'UK');
insert into cust_address values(3,'UAE');
insert into cust_address values(4,'SA');
insert into cust_address values(1,'AUS');
insert into cust_address values(2,'IND');
insert into cust_address values(3,'SL');
insert into cust_address values(1,'CHINA');
Now I want to show the result which contains the latest customer address which have been inserted in the table Cust_Address.
Expected Result:
Cust_ID Cust_Name Cust_Add
-------------------------------
1 A CHINA
2 B IND
3 C SL
4 D SA
Here is the SQLFiddle for tables and its records.
You are not able to retrieve the rows in any particular order. You need some more info to get an order.
The best way is primary index in Cust_address
CustAddrID int identity(1, 1) not null primary key
You can also have a CreatedOn column that will have default value equal to getDate()
After that you can figure out what is the last inserted value for CustAddr for each Cust record.
In case you are not able to add new column there then maybe
change tracking functionality. But your issue seems to be too trivial for that.
There are also Temporal Tables in SQL Server 2016. But again it's probably too much.
Here is an example how you can get the address using primary key CustAddrID
SQL Fiddle
select cust_name, cust_add
from cust C
join
(select
cust_add, cust_id,
row_number() over (partition by cust_id order by cust_add_id desc) rn
from cust_address ) CLA
on CLA.cust_id = C.cust_id and
CLA.rn = 1
Identity column increases every time when we insert new value to the table. The correct value for your case will be the record with the highest cust_add_id and specified cust_id.
In the above query we generates numbers in desc order starting from 1 using row_number() function for each cust_id (partition by cust_id). Finally we take only the records with generated number rn equal to 1 CLA.rn = 1 and we join it to cust table.
You can replace row_number() by max(cust_add_id) and group by cust_id. However in that case you need to join cust_add table twice.
You will not be able to get the rows out of the link table in the order they were inserted.
You need to have a column for this.
Imagine how big the meta-data would be if you needed to keep a record for each record for creation! Would you also want to keep meta-data on your meta-data so you know when the meta-data was updated? The space use can quickly escalate.
SQL Server keeps some stats but something this specific will need to come from a user-defined field.
So you either use a identity column in the CustAddr table [CustAddr int identity(1, 1) not null primary key] or add a column for createdDateAndTime DateTime Default GetDate().

Oracle update statement using multiple columns

I am trying to update price of my products, using another table which has product material and number of that material
my tables are produkt (PRODUKTID int, NAZOV varchar(47), VYROBNA_CENA int)
TABLE material (MATERIALID int, CENA numeric);
TABLE zlozenie (PRODUKTKID int, MATERIALID int, MNOZSTVO int);
what i am trying to do is to put sum(ZLOZENIE.MNOZSTVO*MATERIAL.CENA) to column VYROBNA_CENA
i have two selects that are returning same column, but i am not sure how to use update to transfer values from one to another
first one - calculated price of products
select PRODUKT.NAZOV as NAZOV, sum(ZLOZENIE.MNOZSTVO*MATERIAL.CENA) as celkova
from MATERIAL, PRODUKT, ZLOZENIE
where ZLOZENIE.MATERIALID=MATERIAL.MATERIALID
and PRODUKT.PRODUKTID=ZLOZENIE.PRODUKTKID
group by PRODUKT.NAZOV
order by PRODUKT.NAZOV
second one is table produkt with empty price(cena), and i would like to put results from sum to column cena
select PRODUKT.NAZOV, PRODUKT.vyrobna_cena
from PRODUKT
order by PRODUKT.NAZOV
sql fiddle with tables and queries http://sqlfiddle.com/#!2/e183f/2
thanks
MERGE INTO produkt p
USING
(
SELECT ZLOZENIE.PRODUKTKID, SUM(ZLOZENIE.MNOZSTVO*MATERIAL.CENA) AS celkova
FROM MATERIAL, ZLOZENIE
WHERE ZLOZENIE.MATERIALID=MATERIAL.MATERIALID
GROUP BY ZLOZENIE.PRODUKTKID
) s
ON (p.PRODUKTID = s.PRODUKTKID)
WHEN MATCHED THEN
UPDATE SET VYROBNA_CENA = s.celkova;
Although I would always use join syntax
MERGE INTO produkt p
USING
(
SELECT ZLOZENIE.PRODUKTKID, SUM(ZLOZENIE.MNOZSTVO*MATERIAL.CENA) as celkova
FROM MATERIAL
JOIN ZLOZENIE ON ZLOZENIE.MATERIALID=MATERIAL.MATERIALID
GROUP BY ZLOZENIE.PRODUKTKID
) s
ON (p.PRODUKTID = s.PRODUKTKID)
WHEN MATCHED THEN
UPDATE SET VYROBNA_CENA = s.celkova
Following work is based on your sql fiddle and mysql database.
Change all the decimal columns in your creation scripts from integers to decimal. Following are the updated creation scripts
CREATE TABLE produkt
(`PRODUKTID` int, `NAZOV` varchar(47), `VYROBNA_CENA` decimal(10,2));
CREATE TABLE zlozenie
(`PRODUKTKID` int, `MATERIALID` int, `MNOZSTVO` decimal(10,5));
CREATE TABLE material
(`MATERIALID` int, `CENA` decimal(10,2));
sqlfiddle with updated tables and queries : http://sqlfiddle.com/#!2/0242f/6
Query to update the produckt table
update produkt INNER JOIN
(select ZLOZENIE.PRODUKTKID,sum(ZLOZENIE.MNOZSTVO*MATERIAL.CENA) as celkova
from MATERIAL, ZLOZENIE
where ZLOZENIE.MATERIALID=MATERIAL.MATERIALID
group by ZLOZENIE.PRODUKTKID) ZM
on produkt.PRODUKTKID = ZM.PRODUKTKID
set produkt.VYROBNA_CENA = ZM.celkova
Let me know if this is not what you are after

insert data from one table to another

I have 2 different tables but the columns are named slightly differently.
I want to take information from 1 table and put it into the other table. I need the info from table 1 put into table 2 only when the "info field" in table 1 is not null. Table 2 has a unique id anytime something is created, so anything inserted needs to get the next available id number.
Table 1
category
clientLastName
clientFirstName
incidentDescription
info field is not null then insert all fields into table 2
Table 2
*need a unique id assigned
client_last_name
client_first_name
taskDescription
category
This should work. You don't need to worry about the identify field in Table2.
INSERT INTO Table2
(client_last_name, client_first_name, taskDescription, category)
(SELECT clientLastName, clientFirstName, incidentDescription, category
FROM Table1
WHERE info_field IS NOT NULL)
Member_ID nvarchar(255) primary key,
Name nvarchar(255),
Address nvarchar(255)
)
insert into Member(Member_ID,Name,Address) (select m.Member_Id,m.Name,m.Address from library_Member m WHERE Member_Id IS NOT NULL)