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().
Related
So in this scenario a person can order products. I have a query that returns the result of an order ID and give the products that person ordered.
My issue is adapting this to an update query so the quantity from the OrderProduct table/query is then subtracted from the amount of stock in the Product Table.
SQL to create the table supplied below and the query to get the results
CREATE DATABASE StockControl;
CREATE TABLE Membership (
MemberID int NOT Null,
LastName varchar(255),
FirstName varchar(255),
Primary Key(MemberID)
);
CREATE TABLE Orders (
OrderID int NOT Null,
MemberID int,
Primary Key(OrderID)
);
CREATE TABLE Product (
ProductID int NOT Null,
Price int,
Stock int,
Primary Key(ProductID)
);
CREATE TABLE OrderProduct (
ProductID int,
OrderID int,
Quantity int
);
INSERT INTO Membership(MemberID,LastName,FirstName)
VALUES (2,'Me','Too'),(33,'Darren','Kelly');
INSERT INTO Orders(OrderID,MemberID)
VALUES (1,33),(5,2);
INSERT INTO Product(ProductID,Price,Stock)
VALUES (1,30,12),(2,25,12),(3,25,12),(4,25,12),(5,25,12),(6,25,12),(7,25,12),(8,25,12),(9,25,12),(10,25,12);
INSERT INTO OrderProduct(ProductID,OrderID,Quantity)
VALUES (1,5,1),(3,1,4),(9,1,6),(10,1,2);
This is the query to return all products as part of orderID 1, in the full version this will be able to be variable.
SELECT OrderProduct.ProductID, OrderProduct.OrderID, OrderProduct.Quantity, Product.Price, [Quantity]*[Price] AS Cost
FROM Product INNER JOIN OrderProduct ON Product.ProductID = OrderProduct.ProductID
GROUP BY OrderProduct.ProductID, OrderProduct.OrderID, OrderProduct.Quantity, Product.Price, [Quantity]*[Price]
HAVING (((OrderProduct.OrderID)=1))
ORDER BY OrderProduct.OrderID;
This returns the correct result but when trying to implement this to an update I get stuck. I want it so it looks through the 3 results and will subtract 4 from product 3, 6 from product 9 and 2 from product 10
Attempt so far
UPDATE SingleOrder INNER JOIN Product ON SingleOrder.ProductID = Product.ProductID SET Product.Stock = Product.Stock-SingleOrder.Quantity WHERE ((Product.ProductID=SingleOrder.ProductID));
If this is not clear I am happy to update the question etc.
Thanks
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 am trying to combine insert some field are hardcoded whilst some field are data from other table into my table. How do I do it.
INSERT INTO Orders VALUES('10250', null, null, '1996-07-08', null);
INSERT INTO Orders(OrderID,CustomerID, EmployeeID,ShipperID)
SELECT CustomerID, EmployeeID, ShipperID
FROM Customers,Employees, Shippers
WHERE CustomerID = 34
AND EmployeeID = 4
AND ShipperID =2;
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
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)