SQL Server Management Studio: The multi-part identifier could not be bound - sql

I'm taking a SQL class, and on one of the assignments I am asked to create a table with employees, one with projects, as follows:
create table [EMPLOYEE]
(
EmployeeID int identity(1, 1) primary key not null,
FirstName varchar(15) not null,
LastName varchar(15) not null,
Gender char(1) not null,
DOB date not null,
SSN char(9) not null
)
create table [PROJECT]
(
ProjectID int identity(1, 1) primary key not null,
Manager int not null,
PDescription varchar(50) not null,
PStatus varchar(20) not null,
StartDate date not null,
EndDate date not null
)
Where the Manager is the ID of an EMPLOYEE entity. Basically projects are assigned to employees. So, I add some employees and projects
insert into EMPLOYEE (FirstName, LastName, Gender, DOB, SSN)
values ('Chuck', 'Carter', 'M', '07/14/1990', '444556666')
This is the one employee I'm interested in, and in the inserting I'm doing this is the second one, so its EmployeeID would be 2. As for the projects:
insert into PROJECT (Manager, PDescription, PStatus, StartDate, EndDate)
values (2, 'Submit source code for 3D racing game', 'In progress', '01/05/2015', '03/05/2015')
insert into PROJECT (Manager, PDescription, PStatus, StartDate, EndDate)
values (2, 'Test videogame for bugs', 'Not started', '03/05/2015', '05/05/2015')
These two are the ones assigned to the employee above, notice Manager for both is 2, and the EmployeeID of Chuck is supposed to be 2. So, I'm supposed to display the employee name as a full name, combining the first and last name, of those who have been assigned two or more projects (in this case, Chuck).
I wrote this code:
select
FirstName + LastName as FullName
from
EMPLOYEE
where
EmployeeID = PROJECT.Manager and count(PROJECT.Manager) >= 2
But instantly I get this error:
The multi-part identifier "PROJECT.Manager" could not be bound.
Am I supposed to make an inner join to recognize the PROJECT table? But I'm only supposed to display the name of the employee. How can I manage to use the PROJECT.manager column values without displaying them?
Thank you very much in advance.

You have to Join Project table, Add Group by with having clause to filter the Manager
select FirstName +' '+ LastName as FullName
from EMPLOYEE
INNER JOIN PROJECT
on EmployeeID = PROJECT.Manager
group by FirstName +' '+ LastName
Having count(PROJECT.Manager) >= 2

Related

How to use INSERT INTO SELECT

CREATE TABLE EMPLOYEES (
EMPLOYEEID INT NOT NULL,
DEPARTMENTID INT NOT NULL,
);
CREATE TABLE MANAGERS (
EMPLOYEEID INT NOT NULL,
DEPARTMENTID INT NOT NULL,
ALTER_TIMESTAMP TIMESTAMP NOT NULL
);
I want to insert EMPLOYEES.EMPLOYEEID, EMPLOYEES.DEPARTMENTID, ALTER_TIMESTAMP to MANAGERS table using INSERT INTO SELECT. (ALTER_TIMESTAMP col is current time)
I want this result
enter image description here
this is my code
INSERT INTO MANAGERS
(EMPLOYEEID, DEPARTMENTID, ALTER_TIMESTAMP)
SELECT EMPLOYEEID, DEPARTMENTID, to_char(ALTER_TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS:FF3')
FROM EMPLOYEES, DUAL;
but "ORA-00904: "DUAL"."ALTER_TIMESTAMP": invalid identifier"
You have no column named "alter_timestamp" in your table, this is the cause of the error message.
Try the next insert statement:
INSERT INTO MANAGERS
(EMPLOYEEID, DEPARTMENTID, ALTER_TIMESTAMP)
SELECT EMPLOYEEID, DEPARTMENTID, CURRENT_TIMESTAMP
FROM EMPLOYEES;

SQL Counting on characters

I want to use an SQL statement that returns the department number, department name and the number of employees for each department that has less than 4 employees grouping by department number and department name. I have inputted sample data
CREATE TABLE dbo.Departments
(
First_Name NVARCHAR(20) NOT NULL,
Last_Name NVARCHAR(20) NOT NULL,
Job_Description VARCHAR(30) NULL,
Department_Name VARCHAR(30) NOT NULL,
Department_Number INT NOT NULL,
Date_Hired DATE NOT NULL,
);
INSERT INTO dbo.Departments(First_Name,Last_Name,Job_Description,Department_Name,Department_Number,Date_Hired)
VALUES
('Niel','Matthews','Sales Representative','Marketing',80,'1990-06-12'),
('Jerome','Daniels','Sales Representative','Accounting',60,'1973-03-30'),
('Caleb','Sewcharran','Employee','Accounting',35,'1986-08-10'),
('Orion','Wolf','Employee','Marketing',80,'1987-10-04'),
('Gaige','Johnson','Employee','Accounting',60,'1992-09-22'),
('Maya','Heller','Employee','Marketing',25,'1989-06-17'),
('James','Maroon','Employee','Accounting',30,'2011-08-22'),
('Alex','Mercer','Employee','Accounting',60,'2010-03-17'),
('Adam','Beecher','Sales Representative','Marketing',80,'2012-10-04'),
('Bruce','Wayne','Employee','Marketing',25,'2012-08-12'),
('Al','Kepler','Sales Representative','Accounting',80,'1973-06-30');
I have also attempted an SQL statement but it does not work
SELECT Department_Number,Department_Name,Job_Description
FROM dbo.Departments
WHERE Job_Description='Employee'
(SELECT DISTINCT Department_Name FROM dbo.Departments,
(SELECT CAST('Marketing'AS INT)AS Least_Employees,
CAST('Accounting'AS INT)AS Least_Least_Employees)AS Least_Employees
WHERE Department_Name>4 OR Department_Name>4)
GROUP BY Department_Name AND Department_Number;
Appreciate it if you would tell me what i could have used to get on the right track.
You can use GROUP BY clause :
SELECT Department_Number, Department_Name, COUNT(*) AS NoofEmp
FROM dbo.Departments d
WHERE ob_Description = 'Employee'
GROUP B YDepartment_Number,Department_Name
HAVING COUNT(*) <= 4;

Creating and populating a table in T-SQL

I'm new to T-SQL and trying to learn how to create a script in T-SQL to create and populate a table(StaffData).The StaffData is defined as below:
staffid – integer primary key, identity starting at 1, increments by 1
managerid – int, allows nulls, pointer to another record in managertable
name – string of 50 characters
salary – money
What can I do to generate table and fill it with set of data..?
Here's the correct SQL. I've tested it (just spotted that you want managerId nullable - I've added this):
it uses better conventions for your table and column names (you shouldn't be using 'data' in table names - we know it contains data)
it names your primary key constraints, which is better practice - you can do something similar for the FK constraint if you want, I've just done it inline
it uses 'USE' and 'GO' statements to ensure you're creating things on the right database (critical when you're working on big production systems).
it uses nvarchar columns - you need these to reliably store data from international character sets (e.g the manager has a Russian name)
I'm using nvarchar(max) as you can't be sure that a name will only be 50 characters. Use nvarchar(50) if you must, but database space isn't usually a big deal.
You need to create the Manager table first, as your Staff table depends on it:
USE [yourDatabaseName] -- you don't need the square brackets, but they don't hurt
-- Create ManagerTable
CREATE TABLE Manager
(
id int IDENTITY(1,1),
name nvarchar(max),
CONSTRAINT pk_manager PRIMARY KEY (id)
)
CREATE TABLE Staff
(
id int IDENTITY(1,1),
name nvarchar(max),
salary money,
managerId int FOREIGN KEY REFERENCES Manager(id) NULL,
CONSTRAINT pk_staff PRIMARY KEY (id)
)
--To populate Manager table:
INSERT INTO [Manager]
(
-- id column value is auto-generated
name
)
VALUES
(
'John Doe'
)
--To populate Staff table:
INSERT INTO [Staff]
(
-- id column value is auto-generated
name, salary, managerId
)
VALUES
(
'Jane Doe', 60000, 1
)
GO
To create the two database tables:
-- Create StaffData
CREATE TABLE StaffData
(
staffid int PRIMARY KEY IDENTITY,
managerid int
)
-- Create ManagerTable
CREATE TABLE ManagerTable
(
managerid int,
name varchar(50),
salary money
)
To populate StaffData table:
INSERT INTO [StaffData]
(
--staffid - this column value is auto-generated
[managerid]
)
VALUES
(
-- staffid - int
12345 -- managerid - int
)
To populate ManagerTable table:
INSERT INTO [ManagerTable]
(
[managerid],
[name],
[salary]
)
VALUES
(
12345, -- managerid - int
'Juan Dela Cruz', -- name - varchar
15000 -- salary - money
)
To select the data if i understand you in your word Pointer here is the query using INNER JOIN joining the two tables using their managerid
SELECT *
FROM [StaffData]
INNER JOIN [ManagerTable]
ON [StaffData].managerid = [ManagerTable].managerid

Generating HierarchyID

I would like to insert the hierarchyId like this
/ - CEO (Root)
/1/ - Purchase Manager
/1/1/ - Purchase Executive
/2/ - Sales Manager
/2/1/ - Sales Executive
This is what the hierarchy i would like to use, is it right one, if so how can i do this, can any one give me some code snippet.
I came across this question while searching for information on the hierarchyid data type, and thought it would be interesting for anyone else coming after me to also see code to insert hierarchyids as per the question.
I do not claim that these are the only ways to insert hierarchyids, but hopefully it will help those who, like me, have no previous experience working with this data type.
Using this table,
create table OrgChart
(
Position hierarchyid,
Title nvarchar(50)
)
you can use Parse to directly insert the hierarchyids using the string paths:
insert into OrgChart(Position, Title)
values (hierarchyid::Parse('/'), 'CEO'),
(hierarchyid::Parse('/1/'), 'Purchase Manager'),
(hierarchyid::Parse('/1/1/'), 'Purchase Executive'),
(hierarchyid::Parse('/2/'), 'Sales Manager'),
(hierarchyid::Parse('/2/1/'), 'Sales Executive')
and use the following query to check the table
select Position.ToString(), * from OrgChart
You can also use the hierarchyid data type methods GetRoot and GetDescendant to build the hierarchy. I found this method to be more cumbersome, but I suppose using these methods is necessary if you are programmatically managing the hierarchy.
declare #root hierarchyid,
#id hierarchyid
set #root = hierarchyid::GetRoot()
insert into OrgChart(Position, Title) values (#root, 'CEO')
set #id = #root.GetDescendant(null, null)
insert into OrgChart(Position, Title) values (#id, 'Purchase Manager')
set #id = #root.GetDescendant(#id, null)
insert into OrgChart(Position, Title) values (#id, 'Sales Manager')
select #id = Position.GetDescendant(null, null) from OrgChart where Title = 'Purchase Manager'
insert into OrgChart(Position, Title) values (#id, 'Purchase Executive')
select #id = Position.GetDescendant(null, null) from OrgChart where Title = 'Sales Manager'
insert into OrgChart(Position, Title) values (#id, 'Sales Executive')
Definitely check out the links provided in the other answer, but hopefully having this code to try out will help as well.
Suppose that you have a table schema with a self-join (as shown below) and that the ManagerID of your CEO is NULL.
CREATE TABLE Employee
(
EmployeeID int NOT NULL IDENTITY(1,1) PRIMARY KEY
, JobTitle nvarchar(50) NOT NULL
, FirstName nvarchar(50) NOT NULL
, LastName nvarchar(50)
, ManagerID int
)
ALTER TABLE dbo.Employee ADD CONSTRAINT
FK_Employee_Employee FOREIGN KEY
(
ManagerID
) REFERENCES dbo.Employee
(
EmployeeID
) ON UPDATE NO ACTION
ON DELETE NO ACTION
GO
INSERT INTO Employee(JobTitle, FirstName, LastName, ManagerID)
Values ('Executive', 'Supreme', 'Leader', NULL)
INSERT INTO Employee(JobTitle, FirstName, LastName, ManagerID)
Values ('Manger', 'Boss', 'Man', 1)
INSERT INTO Employee(JobTitle, FirstName, LastName, ManagerID)
Values ('Minion', 'Bob', 'Minion', 2)
INSERT INTO Employee(JobTitle, FirstName, LastName, ManagerID)
Values ('Minion', 'Joe', 'Minion', 2)
GO
You can auto-generate an initial set of hierarchyid values using the following recursive CTE:
;WITH EmployeeHierarchy (
EmployeeHierarchyID
, EmployeeID
, JobTitle
, LastName
, FirstName
, ManagerID
)
AS (
SELECT HIERARCHYID::GetRoot() AS EmployeeHierarchyID
, EmployeeID
, JobTitle
, LastName
, FirstName
, ManagerID
FROM Employee
WHERE ManagerID IS NULL
UNION ALL
SELECT HIERARCHYID::Parse(Manager.EmployeeHierarchyID.ToString() + (
CONVERT(VARCHAR(20), ROW_NUMBER() OVER (
ORDER BY DirectReport.EmployeeID
))
) + '/') AS EmployeeHierarchy
, DirectReport.EmployeeID
, DirectReport.JobTitle
, DirectReport.LastName
, DirectReport.FirstName
, DirectReport.ManagerID
FROM EmployeeHierarchy AS Manager
INNER JOIN Employee AS DirectReport
ON Manager.EmployeeID = DirectReport.ManagerID
)
SELECT EmployeeHierarchyID
, EmployeeID
, JobTitle
, LastName
, FirstName
, ManagerID
INTO #EmployeeHierarchy
FROM EmployeeHierarchy
ORDER BY EmployeeHierarchyID
GO
It then becomes a fairly trivial matter to add a hierarchyid column to the table, add an index on it, and then populate it by joining to the temp table.
ALTER TABLE dbo.Employee ADD
EmployeeHierarchyID hierarchyid NULL
GO
UPDATE Employee
SET Employee.EmployeeHierarchyID = #EmployeeHierarchy.EmployeeHierarchyID
FROM Employee INNER JOIN
#EmployeeHierarchy ON Employee.EmployeeID = #EmployeeHierarchy.EmployeeID
GO
SELECT EmployeeHierarchyID.ToString() AS EmployeeHierarchyIDString, EmployeeID, JobTitle, FirstName, LastName, ManagerID, EmployeeHierarchyID
FROM Employee
GO
However, bear in mind that if you want the hierarchyid data to remain consistent after you add it, there are very specific ways in which it should be maintained.

versioning of a table

anybody has seen any examples of a table with multiple versions for each record
something like if you would had the table
Person(Id, FirstName, LastName)
and you change a record's LastName than you would have both versions of LastName (first one, and the one after the change)
I've seen this done two ways. The first is in the table itself by adding an EffectiveDate and CancelDate (or somesuch). To get the current for a given record, you'd do something like: SELECT Id, FirstName, LastName FROM Table WHERE CancelDate IS NULL
The other is to have a global history table (which holds all of your historical data). The structure for such a table normally looks something like
Id bigint not null,
TableName nvarchar(50),
ColumnName nvarchar(50),
PKColumnName nvarchar(50),
PKValue bigint, //or whatever datatype
OriginalValue nvarchar(max),
NewValue nvarchar(max),
ChangeDate datetime
Then you set a trigger on your tables (or, alternatively, add a policy that all of your Updates/Inserts will also insert into your HX table) so that the correct data is logged.
The way we're doing it (might not be the best way) is to have an active bit field, and a foreign key back to the parent record. So for general queries you would filter on active employees, but you can get the history of a single employee with their Employee ID.
declare #employees
(
PK_emID int identity(1,1),
EmployeeID int,
FirstName varchar(50),
LastName varchar(50),
Active bit,
FK_EmployeeID int
primary key(PK_emID)
)
insert into #employees
(
EmployeeID,
FirstName,
LastName,
Active,
FK_EployeeID
)
select 1, 'David', 'Engle', 1,null
union all
select 2, 'Amy', 'Edge', 0,null
union all
select 2, 'Amy','Engle',1,2