How to split table into multiple tables using SQL - sql

Hi I have this table Cars:
MODEL nvarchar(20)
STYLE nvarchar(20)
ENGINE nvarchar(5)
CAPACITY smallint
MAX_SPEED smallint
PRICE smallmoney
MARKET nvarchar(20)
COMPETITOR nvarchar(20)
And I would like to split it into 3 tables via SQL query:
Cars:
MODEL nvarchar(20)
STYLE nvarchar(20)
MAX_SPEED smallint
PRICE smallmoney
Engine:
ENGINE nvarchar(5)
CAPACITY smallint
Market:
MARKET nvarchar(20)
COMPETITOR nvarchar(20)
So was wandering how this would be done using sql commands, thanks

Easiest way. Select... Into will create new tables:
SELECT DISTINCT
ENGINE,
CAPACITY
INTO Engine
FROM CARS
SELECT DISTINCT
MARKET,
COMPETITOR
INTO Market
FROM CARS
Then just drop the defunct columns from the original table. Eg
ALTER TABLE Cars DROP COLUMN ENGINE
ALTER TABLE Cars DROP COLUMN CAPACITY
ALTER TABLE Cars DROP COLUMN MARKET
ALTER TABLE Cars DROP COLUMN COMPETITOR
This will do specifically what you are asking. However, I'm not sure that is what you want - there is then no reference from the car to the engine or market details - so information is lost.
If "ENGINE" and "MARKET" define the keys of the new table, I'd suggest leaving those columns on the car table as foreign keys. Eg only DROP Capacity and Competitor.
You may wish to create the primary key on the new tables too. Eg:
ALTER TABLE ENGINE ADD CONSTRAINT [PK_Engine] PRIMARY KEY CLUSTERED ENGINE ASC

Run this....
create table Engine
(
EngineId int identity(1,1) not null primary key,
Engine nvarchar(5) not null,
Capacity smallint not null
)
go
insert into Engine
(Engine, Capacity)
(select distinct Engine,Capacity from Cars)
go
alter table Cars
add EngineId int null
go
update Cars
set Cars.EngineId = e.EngineId
from Engine e where e.Engine = Cars.Engine
go
create table Market
(
Id int identity(1,1) not null primary key,
Market nvarchar(20) not null,
Competitor nvarchar(20) not null
)
go
insert into Market
(Market, Competitor)
(select distinct Market,Competitor from Cars)
go
alter table Cars
add MarketId int null
go
update Cars
set Cars.MarketId = m.MarketId
from Market m where m.Market = Cars.Market
go
alter table Cars
drop column Market;
alter table Cars
drop column Competitor;
alter table Cars
drop column Engine;
alter table Cars
drop column Capacity;

To normalize these tables you will firstly need to create new tables, write SQL to insert the data into the new tables and then alter the original table.
See http://technet.microsoft.com/en-us/library/ms174979.aspx
and http://technet.microsoft.com/en-us/library/dd776381(v=sql.105).aspx and http://msdn.microsoft.com/en-us/library/ms190273.aspx

Related

How to create a projection from multi table

I have 2 tables as following:
CREATE TABLE public.test_employee
(
index int NOT NULL,
name varchar(100),
date_of_birth date,
address varchar(100),
id_dep int NOT NULL,
CONSTRAINT C_PRIMARY PRIMARY KEY (index) DISABLED
);
CREATE TABLE store.test_department
(
index int NOT NULL,
name varchar(100),
describe varchar(100),
CONSTRAINT C_PRIMARY PRIMARY KEY (index) DISABLED
);
I need to create a projection with many columns from the above two tables, My current code looks like this:
CREATE PROJECTION public.employee_department_super
(
idEmp,
idDep,
empName,
date_of_birth,
address,
depName,
describe
)
AS
SELECT e.index,
e.id_dep,
e.name,
e.date_of_birth,
e.address,
d.name,
d.describe
FROM
public.test_employee e
inner join store.test_department d
on e.id_dep=d.index
ORDER BY e.name
UNSEGMENTED ALL NODES;
But I received an error:
[Code: 9366, SQL State: 0A000] [Vertica][VJDBC](9366) ROLLBACK: Projections must select data from only one table
How can I solve this problem?
The answer is: you can't.
Join projections were a thing of a long gone past.
Vertica has begun to satisfy the need of reducing joins by the concept of the flattened table.
You add the two columns as flattened columns to your test_employee table, and they are automatically set whenever you insert new rows into the table.
ALTER TABLE public.test_employee
ADD depname VARCHAR(100)
DEFAULT(
SELECT name FROM store.test_department d WHERE d.index=id_dep
);
ALTER TABLE public.test_employee
ADD describe VARCHAR(100)
DEFAULT(
SELECT describe FROM store.test_department d WHERE d.index=id_dep
);
And the two flattened columns do not count against your license size.

Suggested Indexing for table with 50 million rows is queried using its CREATED_DATE column and USER_TYPE column

Table Users:
ID PK INT
USER_TYPE VARCHAR(50) NOT NULL
CREATED_DATE DATETIME2(7) NOT NULL
I have this table with 50 million rows, and it is queries using the following where clause:
WHERE
u.USER_TYPE= 'manager'
AND u.CREATED_DATE >= #StartDate
AND u.CREATED_DATE < #EndDate
What would be a good starting point for an index on this table to optimize for the above query where clause?
For that query, the index you want is a composite index with two columns: (user_type, created_date). The order matters, you want user_type first because of the equality comparison.
You'll be well served by creating a table with user types having an arbitrary INT ID and referring to the manager type by ID, instead of having the manager type directly in the users table. This will narrow the table data as well as any index referring to the user type.
CREATE TABLE user_type (
id INT NOT NULL IDENTITY(1,1),
description NVARCHAR(128) NOT NULL,
CONSTRAINT pk_user_type PRIMARY KEY CLUSTERED(id)
);
CREATE TABLE users (
id INT NOT NULL IDENTITY(1,1),
user_type_id INT NOT NULL,
created_date DATETIME2(7) NOT NULL,
CONSTRAINT pk_users PRIMARY KEY CLUSTERED(id),
CONSTRAINT fk_users_user_type FOREIGN KEY(user_type_id) REFERENCES user_type(id)
);
CREATE NONCLUSTERED INDEX
ix_users_type_created
ON
users (
user_type_id,
created_date
);
You would be querying using the user_type ID rather than directly with the text of course.
For any query. Run the query in SSMS with "Include Actual Execution Plan" on. SSMS will advice an index if it feels proper index doesn't exist.

Computed column from different tables

I have Broadcasts, Agents and Advert tables:
CREATE TABLE Broadcasts (
Broadcast_code INT IDENTITY(1,1)PRIMARY KEY,
Minute_cost SMALLMONEY NOT NULL
);
CREATE TABLE Agents (
Agent_code INT IDENTITY(1,1)PRIMARY KEY,
Agent_percent FLOAT NOT NULL,
);
CREATE TABLE Advert (
Advert_code INT IDENTITY(1,1)PRIMARY KEY,
Agent_commission AS ((Minute_cost * Duration_in_minutes) / Agent_percent),
Broadcast_code INT FOREIGN KEY REFERENCES Broadcasts (Broadcast_code) NOT NULL,
Agent_code INT FOREIGN KEY REFERENCES Agents (Agent_code) NOT NULL
);
I want to calculate a computed column:
Agent_commission AS (((Minute_cost * Duration_in_minutes) / Agent_percent)
I tried to use VIEWS, TRIGGERS and UDF. But I can't do it.
I need the easiest way because this is a training project.
Thanks.
A computed column cannot directly reference columns in other tables. One option is to write a user-defined scalar function to calculate the commission.
You have two other options:
Use a view instead of a table.
Use a user-defined table function.
Which is best depends on how the commission will be used. I would advise you to start with a view with the logic you want. You may find that you want columns from several tables.
You can follow below steps
Create table
CREATE TABLE Advert (
Advert_code INT IDENTITY(1,1)PRIMARY KEY,
Agent_commission INT,
Broadcast_code INT FOREIGN KEY REFERENCES Broadcasts (Broadcast_code) NOT NULL,
Agent_code INT FOREIGN KEY REFERENCES Agents (Agent_code) NOT NULL
);
Select required columns
SELECT
NULL AS Advert_code,
((B.Minute_cost * Duration_in_minutes) / A.Agent_percent),
B.Broadcast_code,
A.Agent_code
FROM Broadcasts B
INNER JOIN Agents A
ON (B.Broadcast_code = A.Agent_code );
Using the select query, you can insert into new tables
INSERT INTO Advert
SELECT
NULL AS Advert_code,
((B.Minute_cost * Duration_in_minutes) / A.Agent_percent),
B.Broadcast_code,
A.Agent_code
FROM Broadcasts B
INNER JOIN Agents A
ON (B.Broadcast_code = A.Agent_code );
Little clarification,
* From where you are getting Duration_in_minutes
* What is Advert_code, right now am selecting null, if required you can use oracle sequence or select from another table.
You can also use same select query to create views

Type collection in a table SQL Server Compact

I work on a program VB.Net using a SQL Server Compact database.
I want to create a table PRODUCTION where I can have many employees so I want to create a column as collection of names of employees:
This is the table Employee :
CREATE TABLE [Employee]
(
[ID] INT NOT NULL IDENTITY (1,1),
[nom] NVARCHAR(100),
[salaire] REAL,
[date_debut] DATETIME,
[tache] NVARCHAR(100)
);
ALTER TABLE [Employe] ADD CONSTRAINT [PK_Employe] PRIMARY KEY ([ID]);
The table PRODUCTION I want to create :
create table production(
ID int not null identity(1,1),
date_prod Datetime,
emp collection (emp1,emp2, ...));
Explanation: in the table Production, I will have many employees, so I want to insert them in one line of the entry.
Any idea?

SQL Server 2008 Foreign Keys that are auto indexed

Are Foreign Keys in SQL Server 2008 are automatically indexed with a value? For Example. if I add a value in my Primary key (or auto incremetend) in may parent table will the table that has a foreign key referenced to that key will automatically have the same value? or I Have to do it explicitly?
No, if you create a foreign key in a child table, it will not automatically get populated when a parent row gets inserted. If you think about this it makes sense. Let's say you have a table like:
CREATE TABLE dbo.Students
(
StudentID INT IDENTITY(1,1) PRIMARY KEY,
Name SYSNAME
);
CREATE TABLE dbo.StudentLoans
(
LoanID INT IDENTITY(1,1) PRIMARY KEY,
StudentID INT FOREIGN KEY REFERENCES dbo.Students(StudentID),
Amount BIGINT -- just being funny
);
What you are suggesting is that when you add a row to Students, the system should automatically add a row to StudentLoans - but what if that student doesn't have a loan? If the student does have a loan, what should the amount be? Should the system pick a random number?
Typically what will happen in this scenario is that you'll be adding a student and their loan at the same time. So if you know the loan amount and the student's name, you can say:
DECLARE
#Name SYSNAME = N'user962206',
#LoanAmount BIGINT = 50000,
#StudentID INT;
INSERT dbo.Students(Name)
SELECT #Name;
SELECT #StudentID = SCOPE_IDENTITY();
INSERT dbo.StudentLoans(StudentID, Amount)
SELECT #StudentID, #LoanAmount;