So I need to present the hierarchy not in rows using f.e. LPAD() but in colums. So for example if I have this relation
Employees (name VARCHAR(15), function VARCHAR(15), #leader)
and functions are from 1 to 6, how to present employees who have function 5 or 6 with all their leaders? I mean if we present that in rows using LPAD and starting from the lower levels it will look like that:
name
Mike -->(function 5)
Bruce
Lee
Lea -->(function 6)
Fred
Mike
Bruce
I need it to look like this:
name function leader1(lowest level) leader2 leader3(highest level in this example)
Mike 5 Bruce Lee
Lea 6 Fred Mike Bruce
and of course it should've been filtered that Mike, Lea etc. have function 5 or 6 and it doesn't matter which function have Bruce, Lee, Fred etc.
ok, to make helping me easier I've created example of database with data with query I use to show the result in rows with LPAD
CREATE TABLE Employees (
name VARCHAR2(15) CONSTRAINT name_pk PRIMARY KEY,
function NUMBER(2) CONSTRAINT function_nn NOT NULL,
leader VARCHAR2(15) CONSTRAINT leader_fk REFERENCES Employees(name)
);
alter table
Employees
DISABLE constraint
leader_fk;
INSERT INTO Employees VALUES ('Mike', 5, 'Lee');
INSERT INTO Employees VALUES ('Bruce', 5, 'Lee');
INSERT INTO Employees VALUES ('Lee', 3, NULL);
INSERT INTO Employees VALUES ('Lea', 6, 'Fred');
INSERT INTO Employees VALUES ('Fred', 1, 'Mike');
alter table
Employees
ENABLE constraint
leader_fk;
WITH
hierarchia (poziom, name, function, leader)
AS (
SELECT 0 poziom, name, function, leader
FROM Employees
WHERE function IN (5, 6)
UNION ALL
SELECT
h.poziom + 1, e.name, e.function, e.leader
FROM hierarchia h, Employees e
WHERE h.leader = e.name
)
SEARCH DEPTH FIRST BY name SET order_by_name
SELECT LPAD(' ', 2*poziom) || name, function
FROM hierarchia
ORDER BY order_by_name;
So it returns correct answer but I need to show LPADed names as neighbour-colums as I've shown in example.
WITH
hierarchia (root, poziom, name, function, leader)
AS (
SELECT name, 0 poziom, name, function, leader
FROM Employees
WHERE function IN (5, 6)
UNION ALL
SELECT h.root,
h.poziom + 1, e.name, e.function, e.leader
FROM hierarchia h, Employees e
WHERE h.leader = e.name
)
select Root, function, Leader1, Leader2 , Leader3 from (
select root, poziom, name from hierarchia )
pivot
(
max(Name)
for poziom in ( 1 as leader1, 2 as leader2, 3 as leader3)
) X
join Employees e
on e.Name = X.root
PIVOT function will change your rows to columns.
Root Function Leader1 Leader2 Leader3
Lea 6 Fred Mike Lee
Bruce 5 Lee
Mike 5 Lee
I hope everyone is fine and learning more. I need some advice on select statement and on its fine tuning. I am using Oracle 11gR2. Please find below table and data scripts.
create table employee (emp_id number, emp_name varchar2(50), manager_id number);
create table department (dept_id number, dept_name varchar2(50), emp_name varchar2(50), manager_level varchar2(20));
create table manager_lookup (manager_level_id number, manager_level varchar2(20));
insert into employee values (1, 'EmpA',3);
insert into employee values (2, 'EmpB',1);
insert into employee values (3, 'EmpC',1);
insert into employee values (4, 'EmpD',2);
insert into employee values (5, 'EmpE',1);
insert into employee values (6, 'EmpF',3);
insert into department values (1, 'DeptA','EmpD','Level3');
insert into department values (2, 'DeptB','EmpC','Level2');
insert into department values (3, 'DeptC','EmpA','Level1');
insert into department values (4, 'DeptD','EmpF','Level1');
insert into department values (5, 'DeptD','EmpA','Level3');
insert into department values (6, 'DeptA',NULL,'Level3');
insert into manager_lookup values (1, 'Level1');
insert into manager_lookup values (2, 'Level2');
insert into manager_lookup values (3, 'Level3');
commit;
Below query is returning me dept_id by passing some emp_name. I need those dept_id where manager_level is same as emp_name passed but don't need to have that same emp_name in result data set.
SELECT b.dept_id
FROM (SELECT DISTINCT manager_level
FROM department dpt
WHERE emp_name = 'EmpA'
and emp_name is not null) a,
department b
WHERE a.manager_level = b.manager_level
AND NVL (b.emp_name, 'ABC') <> 'EmpA';
Above query is returning me data set as below:
dept_id
--------
1
4
6
I want same result set but need to rewrite above query in a way to avoid department table scan two times. This is just sample query but in real time scanning big table two times is giving performance issues. I want to re-write this query in a way to perform better and avoid same table scan two times.
Can you please help on providing your wonderful suggestions or solutions? I will really appreciate all responses.
Thank you for going over the question.
If you want your query to be more efficient, then use indexes:
create index idx_department_name_level on department(emp_name, manager_level)
and
create index idx_department_name_level on department(manager_level, emp_name, dept_id)
also, you have a redundant null check which may be avoiding indexes...
SELECT b.dept_id
FROM (SELECT manager_level
FROM department dpt
WHERE emp_name = 'EmpA') a,
department b
WHERE a.manager_level = b.manager_level
AND NVL (b.emp_name, 'ABC') <> 'EmpA';
post your explain plan for more help
This should work:
SELECT a.*
FROM
(
SELECT d.*,
SUM(CASE WHEN emp_name = 'EmpA' THEN 1 ELSE 0 END)
OVER (PARTITION BY manager_level) AS hits
FROM department d
) a
WHERE hits > 0
AND NVL(emp_name, 'Dummy') <> 'EmpA'
ORDER BY dept_id
;
The query does the following:
Calculate how many times EmpA appears in a given manager_level
Keep all records with a manager_level that has at least one occurrence of EmpA in it
Excluding the EmpA records themselves
SQL Fiddle of the query in action: http://sqlfiddle.com/#!4/a9e03/7
You can verify that the execution plan contains only one full table scan.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Incorrect syntax near insert
For some reason I can't get the tables populated. It worked before but I don't know why it won't run now.
CREATE DATABASE Mort;
Go
USE Mort;
-----------------------------------
/*
**This script creates the
** Employee table with the foreign key
*/
-----------------------------------
----------------------------------------------------
/* I chose Job_title as the PRIMARY KEY.
**All rows must be unique. There is a Job_title
**column in the Employee table that can be used as a
**foreign key.
*/
/*
**This script creates the
** Job title table
*/
----------------------------------------------------
CREATE TABLE
Job_title
(Job_title varchar (50) PRIMARY KEY,
EEO_1_Classification varchar(200),
Job_description varchar(250),
Exempt_Non_Exempt_Status bit );
Go
CREATE TABLE
Employee
(Emp_id int NOT NULL IDENTITY(1,1)PRIMARY KEY,
Last_name varchar(25),
First_name varchar(25),
Address varchar(40),
City varchar (15),
State char(2),
Telephone_area_code varchar(3),
Telephone_number varchar(8),
Job_title varchar(50) foreign key references job_title(job_title),
Hire_date smalldatetime,
Wage money,
Gender char(1),
Race varchar(25),
Age int );
-----------------------------------------------------------------------------------------------------
/* (3.1) This script inserts employee records
** for both the administrative offices
** and the Del Mar location
*/
-------------------------------------------------------------------------------------------------
USE Mort;
Go
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
VALUES
('McNamara',
'Juanita',
'923 Parkway',
'La Jolla',
'CA',
'619',
'555-0208',
'Accounting Clerk',
'10/07/2003',
'$12.75',
'F',
'Hispanic',
32);
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
VALUES
('Stephens',
'Harvey',
'7863 High Bluff Drive',
'La Jolla',
'CA',
'619',
'555-0123',
'Dir. of Fin.
& Acct.',
'3/1/1998',
'$75,000.00',
'M',
'Caucasian',
51);
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
VALUES
('Vu',
'Matthew',
'981 Torrey Pines Road',
'La Jolla',
'CA',
'619',
'555-0138',
'Computer Support Specialist',
'8/16/2000',
'$18.50',
'M',
'Asian',
26);
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
VALUES
('Nguyen',
'Meredith',
'10583 Arenas ST. ',
'La Jolla ',
'CA',
'619',
'555-0102',
'Computer Support Specialist ',
'9/27/1998 ',
'$21.50 ',
'M',
'Caucasian',
25);
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
VALUES
('Avery',
'Ledonna',
'198 Governor Dr.',
'Del Mar',
'CA',
'619',
'555-0135',
'Asst. - Bakery & Pastry',
'3/28/2003',
'$10.50',
'F',
'African American',
23);
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
VALUES
('Drohos',
'Craig',
' ',
'Selano Beach',
'CA',
'619',
'555-0202',
'Assistant Manager',
'6/15/2000',
'$51,000.00 ',
'M',
'Caucasian',
32);
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
VALUES
('Meier',
'Elaine',
'9703 Orchid Lane',
'Del Mar',
'CA',
'858',
'555-0112',
'Cashier',
'9/10/2000',
'$10.25',
'F',
'Asian',
51);
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
VALUES
('Quillian',
'Stanley',
'98542 Wandering Road Apt 2-B',
'Del Mar',
'CA',
'760',
'555-0198',
'Asst. - Butchers & Seafood Specialists',
'12/16/1999',
'$11.50 ',
'M',
'American Indian',
29);
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
VALUES
('Tyink',
'Thomas',
'87592 Pacific Heights Blvd.',
'Del Mar',
'CA',
'858',
'555-0159',
'Asst. - Bakery & Pastry',
'5/1/2001',
'$9.50',
'M',
'African American',
32);
INSERT INTO
Employee
(Last_name,
First_name,
Address,
City,
State,
Telephone_area_code,
Telephone_number,
Job_title,
Hire_date,
Wage,
Gender,
Race,
Age)
VALUES
('Vance',
'Brent',
'927 Cynthia Lane Parkway',
'Del Mar',
'CA',
'858',
'555-0147',
'Bagger - 30 hours/wk',
'3/29/2001',
'$6.75',
'M',
'Caucasian',
22);
------------------------------------------------------
/* This script inserts values into Job_title table
** Note: 1 means exempt (salaried)
** 0 means non-exempt (hourly)
** Section (2.2)
*/
------------------------------------------------------
INSERT INTO Job_title
(Job_title, EEO_1_Classification, Job_description, Exempt_Non_Exempt_Status )
VALUES
('Accounting Clerk', 'Office/Clerical',
'Computes, classifies, records, and verifies numerical data for use in maintaining
accounting records.',
0);
INSERT INTO Job_title
(Job_title, EEO_1_Classification, Job_description, Exempt_Non_Exempt_Status )
VALUES
('Assistant Manager', 'Officials & Managers',
'Supervises and coordinates activities of workers in department of food store.
Assists store manager in daily operations of store.' ,
1);
INSERT INTO Job_title
(Job_title, EEO_1_Classification, Job_description, Exempt_Non_Exempt_Status )
VALUES
('Bagger','Sales Workers',
'Places customer orders in bags. Performs carryout duties for customers.',
0);
INSERT INTO Job_title
(Job_title, EEO_1_Classification, Job_description, Exempt_Non_Exempt_Status )
VALUES
('Cashier','Sales Workers',
'Operates cash register to itemize and total customer’s purchases in grocery
store.',
0);
INSERT INTO Job_title
(Job_title, EEO_1_Classification, Job_description, Exempt_Non_Exempt_Status )
VALUES
('Computer Support Specialist','Technician',
'Installs, modifies, and makes minor repairs to personal computer hardware and
software systems, and provides technical assistance and training to system
users.',
0);
INSERT INTO Job_title
(Job_title, EEO_1_Classification, Job_description, Exempt_Non_Exempt_Status )
VALUES
('Dir. of Fin. & Acct.','Officials & Managers',
'Plans and directs the finance and accounting activities for Kudler Fine Foods.',
1);
INSERT INTO Job_title
(Job_title, EEO_1_Classification, Job_description, Exempt_Non_Exempt_Status )
VALUES
('Asst. - Bakery & Pastry','Craft Workers (Skilled)',
'Obtains or prepares food items requested by customers in retail food store.',
0);
INSERT INTO Job_title
(Job_title, EEO_1_Classification, Job_description, Exempt_Non_Exempt_Status )
VALUES
('Asst. - Butchers & Seafood Specialists','Operatives (Semi skilled)',
'Obtains or prepares food items requested by customers in retail food store.',
0);
INSERT INTO Job_title
(Job_title, EEO_1_Classification, Job_description, Exempt_Non_Exempt_Status )
VALUES
('Stocker','Office/Clerical',
'Stores, prices and restocks merchandise displays in store.',
0)
------------------------------------------------------------------------------------------
/*
**(3.2) This script Checks the results by selecting
**all of the columns from both of the tables
**Select * from
**Select * from
*/
/*
**Format of Employee table due to requirement
**Do not “string out” an entire query/statement so
**that it requires the viewer to horizontally scroll to read it.
*/
-------------------------------------------------------------------------------------------
USE Mort;
Select Emp_id, Last_name, First_name, Address, City, State from Employee
Go
Select Telephone_area_code, Telephone_number, Job_title, Hire_date, Wage, Gender, Race, Age from Employee
Go
Select * from Job_title
Go
/*
**(3.3) Write a SQL query that joins two tables in the example database and uses BETWEEN **to restrict record selection. (Use salary to restrict the data.)
*/
Select Employee.Wage, Job_title.Job_title
From Employee
inner join Job_title
on Employee.Wage=Job_title.Job_title
order by Employee.Last_name
(3.4) Write a SQL query that joins two tables in the example database and uses BETWEEN to restrict record selection. (Use hire dates to restrict the data.)
(3.5) Write a SQL query that joins two tables in the example database and uses LIKE to restrict record selection. (Use telephone area codes to restrict data.)
(3.6) Write a SQL query that joins two tables in the example database and uses LIKE to restrict record selection. (Use age to find all people in their 20’s.)
(3.7) Write a SQL query that uses UNION of the two tables. Be creative.
(3.8) Write a SQL query that displays the average salary / hourly wage grouped by job_title.
(3.9) Write a SQL query that displays the number of people in each EE0-1 Classification and the average salary / hourly wage for each classification.
(3.10) Group employees by EEO classification: Select the employees’ last names and group them by EEO-1 Classification
(3.11) Group employees by salary within their EEO classification: Select the employees’ last names and group them by salary within their EEO-1 Classification.
(3.12) Select the employees’ last names and group them by salary within job titles that are grouped into exempt and non-exempt.
You don't have a VALUES section for one of the INSERT's(the 6th INSERT)
I'm looking for a good solution to use the containstable feature of the SQL Serve r2005 effectivly. Currently I have, e.g. an Employee and an Address table.
-Employee
Id
Name
-Address
Id
Street
City
EmployeeId
Now the user can enter search terms in only one textbox and I want this terms to be split and search with an "AND" operator. FREETEXTTABLE seems to work with "OR" automatically.
Now lets say the user entered "John Hamburg". This means he wants to find John in Hamburg.
So this is "John AND Hamburg".
So the following will contain no results since CONTAINSTABLE checks every column for "John AND Hamburg".
So my question is: What is the best way to perform a fulltext search with AND operators across multiple columns/tables?
SELECT *
FROM Employee emp
INNER JOIN
CONTAINSTABLE(Employee, *, '(JOHN AND Hamburg)', 1000) AS keyTblSp
ON sp.ServiceProviderId = keyTblSp.[KEY]
LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = emp.EmployeeId
UNION ALL
SELECT *
FROM Employee emp
LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = emp.EmployeeId
INNER JOIN
CONTAINSTABLE([Address], *, '(JOHN AND Hamburg)', 1000) AS keyTblAddr
ON addr.AddressId = keyTblAddr.[KEY]
...
This is more of a syntax problem. How do you divine the user's intent with just one input box?
Are they looking for "John Hamburg" the person?
Are they looking for "John Hamburg Street"?
Are they looking for "John" who lives on "Hamburg Street" in Springfield?
Are they looking for "John" who lives in the city of "Hamburg"?
Without knowing the user's intent, the best you can hope for is to OR the terms, and take the highest ranking hits.
Otherwise, you need to program in a ton of logic, depending on the number of words passed in:
2 words:
Search Employee data for term 1, Search Employee data for term 2, Search Address data for term 1, Search address data for term 2. Merge results by term, order by most hits.
3 words:
Search Employee data for term 1, Search Employee data for term 2, Search employee data for term 3, Search Address data for term 1, Search address data for term 2, Search address data for term 3. Merge results by term, order by most hits.
etc...
I guess I would redesign the GUI to separate the input into Name and Address, at a minimum. If that is not possible, enforce a syntax rule to the effect "First words will be considered a name until a comma appears, any words after that will be considered addresses"
EDIT:
Your best bet is still OR the terms, and take the highest ranking hits. Here's an example of that, and an example why this is not ideal without some pre-processing of the input to divine the user's intent:
insert into Employee (id, [name]) values (1, 'John Hamburg')
insert into Employee (id, [name]) values (2, 'John Smith')
insert into Employee (id, [name]) values (3, 'Bob Hamburg')
insert into Employee (id, [name]) values (4, 'Bob Smith')
insert into Employee (id, [name]) values (5, 'John Doe')
insert into Address (id, street, city, employeeid) values (1, 'Main St.', 'Springville', 1)
insert into Address (id, street, city, employeeid) values (2, 'Hamburg St.', 'Springville', 2)
insert into Address (id, street, city, employeeid) values (3, 'St. John Ave.', 'Springville', 3)
insert into Address (id, street, city, employeeid) values (4, '5th Ave.', 'Hamburg', 4)
insert into Address (id, street, city, employeeid) values (5, 'Oak Lane', 'Hamburg', 5)
Now since we don't know what keywords will apply to what table, we have to assume they could apply to either table, so we have to OR the terms against each table, UNION the results, Aggregate them, and compute the highest rank.
SELECT Id, [Name], Street, City, SUM([Rank])
FROM
(
SELECT emp.Id, [Name], Street, City, [Rank]
FROM Employee emp
JOIN [Address] addr ON emp.Id = addr.EmployeeId
JOIN CONTAINSTABLE(Employee, *, 'JOHN OR Hamburg') AS keyTblEmp ON emp.Id = keyTblEmp.[KEY]
UNION ALL
SELECT emp.Id, [Name], Street, City, [Rank]
FROM Employee emp
JOIN [Address] addr ON emp.Id = addr.EmployeeId
JOIN CONTAINSTABLE([Address], *, 'JOHN OR Hamburg') AS keyTblAdd ON addr.Id = keyTblAdd.[KEY]
) as tmp
GROUP BY Id, [Name], Street, City
ORDER BY SUM([Rank]) DESC
This is less than ideal, here's what you get for the example (in your case, you would have wanted John Doe from Hamburg to show up first):
Id Name Street City Rank
2 John Smith Hamburg St. Springville 112
3 Bob Hamburg St. John Ave. Springville 112
5 John Doe Oak Lane Hamburg 96
1 John Hamburg Main St. Springville 48
4 Bob Smith 5th Ave. Hamburg 48
But that is the best you can do without parsing the input before submitting it to SQL to make a "best guess" at what the user wants.
I had the same problem. Here is my solution, which worked for my case:
I created a view that returns the columns that I want. I added another extra column which aggregates all the columns I want to search among. So, in this case the view would be like
SELECT emp.*, addr.*, ISNULL(emp.Name,'') + ' ' + ISNULL(addr.City, '') AS SearchResult
FROM Employee emp
LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = emp.EmployeeId
After this I created a full-text index on SearchResult column. Then, I search on this column
SELECT *
FROM vEmpAddr ea
INNER JOIN CONTAINSTABLE(vEmpAddr, *, 'John AND Hamburg') a ON ea.ID = a.[Key]