I have a two tables and details are give below:
create table pbc(
id number(5) primary key,
name varchar2(15));
insert into pbc values(2,'product1');
insert into pbc values(3,'product1');
insert into pbc values(4,'product1');
insert into pbc values(5,'product1');
insert into pbc values(6,'product1');
insert into pbc values(7,'product1');
and the other table is
create table zxy(
id number(5),
price number(10));
alter table zxy add(constraint zxyid_fk FOREIGN KEY (id) references pbc(id));
insert into zxy values(2,67);
insert into zxy values(3,34);
insert into zxy values(3,21);
insert into zxy values(4,65);
insert into zxy values(5,32);
insert into zxy values(5,23);
insert into zxy values(5,10);
second table select data are given below
Id price
2 67
3 34
3 21
4 65
5 32
5 23
5 10
now i have to select last inserting values such as
id price
2 67
3 21
4 65
5 10
I do not want to max price I want to last insert price
There is no way to say which value was inserted last. For ID 3 there are two prices 34 and 21, but nothing to indicate when the records got inserted. Data in tables has no inherent order; the records are considered unordered.
You need a date or something to indicate insert order.
If the table already exists this way, you are lost, because you cannot know which values are current and which are out-dated. If this is a new table and you only plan to fill it later, then add a date and a trigger to fill the date with sysdate on insert.
Based on the requirements, I don't see any usage of the first table. Try:
SELECT Z.ID, B.PRICE
FROM
(
SELECT A.ID, MAX(A.RNUM) AS LAST_INSERTED
FROM
(SELECT ID, PRICE, ROW_NUMBER() OVER (PARTITION BY ID) AS RNUM FROM ZXY) A
GROUP BY A.ID
) Z
INNER JOIN
(SELECT ID, PRICE, ROW_NUMBER() OVER (PARTITION BY ID) AS RNUM FROM ZXY) B
ON Z.ID = B.ID AND Z.LAST_INSERTED = B.RNUM;
Related
Lets say I have given table:
1 A
2 A
3 A
How do I JOIN / combine the table with itself so I get every possible unique pair combination of the first column:
1 1 A
1 2 A
1 3 A
2 1 A
2 2 A
2 3 A
...
You can do something like this.
Cross JOIN is used for cross product
-- create
CREATE TABLE EMPLOYEE (
empId INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
-- insert
INSERT INTO EMPLOYEE VALUES (0001, 'Clark');
INSERT INTO EMPLOYEE VALUES (0002, 'Dave');
INSERT INTO EMPLOYEE VALUES (0003, 'Ava');
-- fetch
SELECT e1.empId, e2.empId, e1.name FROM EMPLOYEE e1
CROSS JOIN EMPLOYEE e2;
I will create table where I will insert multiple values for different companies. Basically I have all values that are in the table below but I want to add a column IndicatorID which is linked to IndicatorName so that every indicator has a unique id. This will obviously not be a PrimaryKey.
I will insert the data with multiple selects:
CREATE TABLE abc
INSERT INTO abc
SELECT company_id, 'roe', roevalue, metricdate
FROM TABLE1
INSERT INTO abc
SELECT company_id, 'd/e', devalue, metricdate
FROM TABLE1
So, I don't know how to add the IndicatorID I mentioned above.
EDIT:
Here is how I populate my new table:
INSERT INTO table(IndicatorID, Indicator, Company, Value, Date)
SELECT [the ID that I need], 'NI_3y' as 'Indicator', t.Company, avg(t.ni) over (partition by t.Company order by t.reportdate rows between 2 preceding and current row) as 'ni_3y',
t.reportdate
FROM table t
LEFT JOIN IndicatorIDs i
ON i.Indicator = roe3 -- the part that is not working if I have separate indicatorID table
I am going to insert different indicators for the same companies. And I want indicatorID.
Your "indicator" is a proper entity in its own right. Create a table with all indicators:
create table indicators (
indicator_id int identity(1, 1) primary key,
indicator varchar(255)
);
Then, use the id only in this table. You can look up the value in the reference table.
Your inserts are then a little more complicated:
INSERT INTO indicators (indicator)
SELECT DISTINCT roevalue
FROM table1 t1
WHERE NOT EXISTS (SELECT 1 FROM indicators i2 WHERE i2.indicator = t1.roevalue);
Then:
INSERT INTO ABC (indicatorId, companyid, value, date)
SELECT i.indicatorId, t1.company, v.value, t1.metricdate
FROM table1 t1 CROSS APPLY
(VALUES ('roe', t1.roevalue), ('d/e', t1.devalue)
) v(indicator, value) JOIN
indicators i
ON i.indicator = v.indicator;
This process is called normalization and it is the typical way to store data in a database.
DDL and INSERT statement to create an indicators table with a unique constraint on indicator. Because the ind_id is intended to be a foreign key in the abc table it's created as a non-decomposable surrogate integer primary key using the IDENTITY property.
drop table if exists test_indicators;
go
create table test_indicators (
ind_id int identity(1, 1) primary key not null,
indicator varchar(20) unique not null);
go
insert into test_indicators(indicator) values
('NI'),
('ROE'),
('D/E');
The abc table depends on the ind_id column from indicators table as a foreign key reference. To populate the abc table company_id's are associated with ind_id's.
drop table if exists test_abc
go
create table test_abc(
a_id int identity(1, 1) primary key not null,
ind_id int not null references test_indicators(ind_id),
company_id int not null,
val varchar(20) null);
go
insert into test_abc(ind_id, company_id)
select ind_id, 102 from test_indicators where indicator='NI'
union all
select ind_id, 103 from test_indicators where indicator='ROE'
union all
select ind_id, 104 from test_indicators where indicator='D/E'
union all
select ind_id, 103 from test_indicators where indicator='NI'
union all
select ind_id, 105 from test_indicators where indicator='ROE'
union all
select ind_id, 102 from test_indicators where indicator='NI';
Query to get result
select i.ind_id, a.company_id, i.indicator, a.val
from test_abc a
join test_indicators i on a.ind_id=i.ind_id;
Output
ind_id company_id indicator val
1 102 NI NULL
2 103 ROE NULL
3 104 D/E NULL
1 103 NI NULL
2 105 ROE NULL
1 102 NI NULL
I was finally able to find the solution for my problem which seems to me very simple, although it took time and asking different people about it.
First I create my indicators table where I assign primary key for all indicators I have:
CREATE TABLE indicators (
indicator_id int identity(1, 1) primary key,
indicator varchar(255)
);
Then I populate easy without using any JOINs or CROSS APPLY. I don't know if this is optimal but it seems as the simplest choice:
INSERT INTO table(IndicatorID, Indicator, Company, Value, Date)
SELECT
(SELECT indicator_id from indicators i where i.indicator = 'NI_3y) as IndicatorID,
'NI_3y' as 'Indicator',
Company,
avg(ni) over (partition by Company order by reportdate rows between 2 preceding and current row) as ni_3y,
reportdate
FROM TABLE1
I have a table which needs to have a composite primary key based on 2 columns (Material number, Plant).
For example, this is how it is currently (note that these rows are not unique):
MATERIAL_NUMBER PLANT NUMBER
------------------ ----- ------
000000000000500672 G072 1
000000000000500672 G072 1
000000000000500672 G087 1
000000000000500672 G207 1
000000000000500672 G207 1
However, I'll need to add the additional column (NUMBER) to the composite key such that each row is unique, and it must work like this:
For each MATERIAL_NUMBER, for each PLANT, let NUMBER start at 1 and increment by 1 for each duplicate record.
This would be the desired output:
MATERIAL_NUMBER PLANT NUMBER
------------------ ----- ------
000000000000500672 G072 1
000000000000500672 G072 2
000000000000500672 G087 1
000000000000500672 G207 1
000000000000500672 G207 2
How would I go about achieving this, specifically in SQL Server?
Best Regards!
SOLVED.
See below:
SELECT MATERIAL_NUMBER, PLANT, (ROW_NUMBER() OVER (PARTITION BY MATERIAL_NUMBER, PLANT ORDER BY VALID_FROM)) as NUMBER
FROM Table_Name
Will output the table in question, with the NUMBER column properly defined
Suppose this is actual table,
create table #temp1(MATERIAL_NUMBER varchar(30),PLANT varchar(30), NUMBER int)
Suppose you want to insert only single record then,
declare #Num int
select #Num=isnull(max(number),0) from #temp1 where MATERIAL_NUMBER='000000000000500672' and PLANT='G072'
insert into #temp1 (MATERIAL_NUMBER,PLANT , NUMBER )
values ('000000000000500672','G072',#Num+1)
Suppose you want to insert bulk record.Your bulk record sample data is like
create table #temp11(MATERIAL_NUMBER varchar(30),PLANT varchar(30))
insert into #temp11 (MATERIAL_NUMBER,PLANT)values
('000000000000500672','G072')
,('000000000000500672','G072')
,('000000000000500672','G087')
,('000000000000500672','G207')
,('000000000000500672','G207')
You want to insert `#temp11` in `#temp1` maintaining number id
insert into #temp1 (MATERIAL_NUMBER,PLANT , NUMBER )
select t11.MATERIAL_NUMBER,t11.PLANT
,ROW_NUMBER()over(partition by t11.MATERIAL_NUMBER,t11.PLANT order by (select null))+isnull(maxnum,0) as Number from #temp11 t11
outer apply(select MATERIAL_NUMBER,PLANT,max(NUMBER)maxnum from #temp1 t where t.MATERIAL_NUMBER=t11.MATERIAL_NUMBER
and t.PLANT=t11.PLANT group by MATERIAL_NUMBER,PLANT) t
select * from #temp1
drop table #temp1
drop table #temp11
Main question is Why you need number column ? In mot of the cases you don't need number column,you can use ROW_NUMBER()over(partition by t11.MATERIAL_NUMBER,t11.PLANT order by (select null)) to display where you need. This will be more efficient.
Or tell the actual situation and number of rows involved where you will be needing Number column.
i have created tables item and item2, I know maybe it's data redundancy but i want to know how can select it, and create a view?
create table item(
id number(10) primary key,
name varchar2(20),
mark number(10));
insert into item values(10,'Apple1',23);
insert into item values(11,'Apple2',0);
insert into item values(12,'Apple3',0);
insert into item values(13,'Apple4',0);
insert into item values(14,'Apple4',0);
insert into item values(15,'Apple4',0);
insert into item values(16,'Apple4',0);
create table item2(
id number(10),
mark number(10));
alter table item2 add(constraint id_fk FOREIGN KEY (id) references item(id));
Insert into item2 values(10,1);
Insert into item2 values(10,1);
Insert into item2 values(11,7);
Insert into item2 values(12,14);
I can query both:
select * from item;
ID Name Mark
10 Apple1 23
11 Apple2 0
12 Apple3 0
13 Apple4 0
14 Apple4 0
15 Apple4 0
16 Apple4 0
select * from item2;
ID Mark
10 1
10 1
11 7
12 14
I want to get the result set below using the select statement sum from the item and item2 tables:
ID Name Mark
10 Apple1 25
11 Apple2 7
12 Apple3 14
13 Apple4 0
14 Apple4 0
15 Apple4 0
16 Apple4 0
How can I combine my queries to produce that output?
If I understand this correctly, you want to "pretend" that the second table had the NAME column also, populated according to the first table; then you would want to GROUP BY id and get the sum of MARK.
If so, instead of joining the tables to get the names (either before or after combining the tables and computing the sums), you can use a UNION ALL, in which you insert a fake NAME column with NULL in it for the second table; then you group by id, you sum the MARK column, and you take the MAX over NAME. MAX ignores NULL, so it will just pick the name from table ITEM.
The solution below follows that logic in every detail.
select id, max(name) as name, sum(mark) as mark
from ( select id, name, mark
from item
union all
select id, null as name, mark
from item2
)
group by id
;
You can union the two tables together on the id and mark. The name you can either add a null name column into the union and do a max/min on that field to get one value from that table. Otherwise you can union the id and marks, and then join back to the original table with the name to grab it from there and include it in the group by.
select item_table.id, item_table.name, sum(mark_data_set.mark) as mark_score
from
(select
id, mark
from item
union all
select id, mark
from item2
) mark_data_set
inner join item item_table on (mark_data_set.id = item_table.id)
group by item_table.id, item_table.name
How about this?
select id,name,(m1 +nvl(m2,0)) mark
from
(select t1.id,t1.name,t1.mark m1,t2.mark m2
from
item t1
LEFT OUTER JOIN
(select id,sum(mark) mark from item2
group by id) t2
ON
t2.id = t1.id
)
order by id;
I have this sample.
What I need is getting an average per key not key and value. However, the syntax I used appear to give me the average per key and value.
select avg(value2),KEY,VALUE from testavg
GROUP BY key,value
order by key, value
Doing otherwise will yield a syntax error. The results I need are as follow:
10 A 0.96
10 B 0.04
12 C 1
But the statement I used yields the incorrect results above.
Could this be achieved by issuing 1 single oracle select statement? I have included the statement to create the entire table.
CREATE TABLE "TESTAVG"
( "KEY" NUMBER,
"VALUE" VARCHAR2(20 BYTE),
"VALUE2" NUMBER
)
Insert into TESTAVG (KEY,VALUE,VALUE2) values (10,'A',12);
Insert into TESTAVG (KEY,VALUE,VALUE2) values (10,'A',13);
Insert into TESTAVG (KEY,VALUE,VALUE2) values (10,'B',1);
Insert into TESTAVG (KEY,VALUE,VALUE2) values (12,'C',20);
This query might run faster on larger data - only reads the table once:
select distinct key, value,
sum(value2) over (partition by key, value) / sum(value2) over (partition by key) r
from testavg
/
KEY VALUE R
---------- -------------------- ----------
10 A .961538462
10 B .038461538
12 C 1
select avg(value2),KEY from testavg
GROUP BY key
order by key;
8.66666666666666666666666666666666666667 10
20 12
EDIT: Specs are still not clear but this might be what you need...
with gr1 as (select key,sum(value2) sumvalue
from testavg
group by key)
, gr2 as (select key,value,sum(value2) sumvalue
from testavg
GROUP BY key,value)
select gr1.key,gr2.value,gr2.sumvalue/gr1.sumvalue
from gr1
, gr2
where gr1.key = gr2.key;
10 B 0.0384615384615384615384615384615384615385
12 C 1
10 A 0.9615384615384615384615384615384615384615