Substitution Variable: Specifying Column Names, Expressions, and Text - oracle11g

When I type & execute this query in PL/SQL Developer:
select employee_id, first_name, last_name, job_id, &column_name
from employees WHERE &condition ORDER BY &order_column
I got the error message:
ORA-00936:missing expression.
Although when I execute this query, variables field prompt up on my screen with three field names respectively column_name, condition and order_column.
After entering the values in the above three fields respectively-- salary, >10000, employee/-id When I click ok, I get the above mentioned error message.
Can anyone please help to sort out this issue?

If you try to run your query in SQLPlus, it will show you how your query is transformed by the usage of the values you give to the variables:
SQL> select employee_id, first_name, last_name, job_id, &column_name from employees WHERE &condition ORDER BY &order_column;
Enter value for column_name: salary
Enter value for condition: >1000
Enter value for order_column: employee/-id
old 1: select employee_id, first_name, last_name, job_id, &column_name from employees WHERE &condition ORDER BY &order_column
new 1: select employee_id, first_name, last_name, job_id, salary from employees WHERE >1000 ORDER BY employee/-id
select employee_id, first_name, last_name, job_id, salary from employees WHERE >1000 ORDER BY employee/-id
*
ERROR at line 1:
ORA-00936: missing expression
So, your query becomes the following:
select employee_id, first_name, last_name, job_id, salary from employees
WHERE >1000 ORDER BY employee/-id
which is obviously wrong.
You need to give a well format condition ( for example salary > 1000) and to use the right column identifiers for the ORDER BY clause ( say employee_id); for example:
SQL> select employee_id, first_name, last_name, job_id, &column_name from employees WHERE &condition ORDER BY &order_column;
Enter value for column_name: salary
Enter value for condition: salary > 10000
Enter value for order_column: employee_id
old 1: select employee_id, first_name, last_name, job_id, &column_name from employees WHERE &condition ORDER BY &order_column
new 1: select employee_id, first_name, last_name, job_id, salary from employees WHERE salary > 10000 ORDER BY employee_id
EMPLOYEE_ID FIRST_NAME LAST_NAME JOB_ID SALARY
----------- -------------------- ------------------------- ---------- ----------
100 Steven King AD_PRES 24000
101 Neena Kochhar AD_VP 17000
...
15 rows selected.
SQL>

Is that your column name? employee/-id? That may be part of your problem here.
Basically using anything different than:
Alphabets
Numbers (not at start of the column name)
Underscore (_)
is not recommended as it is not a good way to name fields and some datasources might throw errors on other characters.

Related

UNION not working Teradata SQL. Syntax error: Top N option is not allowed in a query connected by set operators

When I run both queries individually, they run correctly. But when I try to combine both result sets into one table using the UNION operator, it doesn't run and I get the error message : "Syntax error: Top N option is not allowed in a query connected by set operators."
select
top 1
city,
count(*)
from unicorns
where city is not null and industry = 'Edtech'
group by city
order by 2 desc
union
select
top 1
city,
count(*)
from unicorns
where city is not null and industry = 'Internet software & services'
group by city
order by 2 desc
I would appreciate any help,
Thanks.
Instead you can use window functions to achieve the same:
select
city,
count(*) ccount
from unicorns
where city is not null and industry = 'Edtech'
group by city
QUALIFY ROW_NUMBER() OVER (ORDER BY ccount DESC) = 1
union
select
city,
count(*) ccount
from unicorns
where city is not null and industry = 'Internet software & services'
group by city
QUALIFY ROW_NUMBER() OVER (ORDER BY ccount DESC) = 1
This way you aren't relying on ordering/top an interim result set (outside of partition ordering) and Teradata will be ok with it.
It's probably because the optimizer doesn't know if the 2nd ORDER BY is part of the top or the final ORDER BY of the UNION.
The common workaround for this type of error is to wrap the Selects in Derived Tables/CTEs:
select *
from
(
select
top 1
city,
count(*)
from unicorns
where city is not null and industry = 'Edtech'
group by city
order by 2 desc
) as dt
union
select *
from
(
select
top 1
city,
count(*)
from unicorns
where city is not null and industry = 'Internet software & services'
group by city
order by 2 desc
) as dt

Check if rows were selected PLSQL

Well I have a procedure were I add two the salary of two employees. I get the salary with the id of the employee. If the employee was not found I should set the salary to 0. This is my code
PROCEDURE private_salaries(
sal_res OUT NUMBER,
emp_1 NUMBER,
emp_2 NUMBER)
IS
sal_1 NUMBER;
sal_2 NUMBER;
BEGIN
SELECT salary INTO sal_1 FROM employees WHERE employee_id = emp_1;
SELECT salary INTO sal_2 FROM employees WHERE employee_id = emp_2;
END;
The procedure can be simplified as below,
create or replace PROCEDURE private_salaries(
emp_1 NUMBER,
emp_2 NUMBER,
sal_res out NUMBER)
is
begin
select sal1 + sal2 into sal_res
from
(
select
nvl((SELECT salary FROM employees WHERE employee_id = emp_1),0) sal1,
nvl((SELECT salary FROM employees WHERE employee_id = emp_2),0) sal2
from dual);
end;
Test Cases :
When both of them exists - Returns sum of the salary
When either one doesn't exists - Returns salary of one that exists
When none of them exists - Returns zero.
Recommendation - Use function instead of procedure and you may use them in SQL,for procedure a PL/SQL block is required though.

SQLite Nested Query for maximum

I'm trying to use DB Browser for SQLite to construct a nested query to determine the SECOND highest priced item purchased by the top 10 spenders. The query I have to pick out the top 10 spenders is:
SELECT user_id, max(item_total), SUM (item_total + shipping_cost -
discounts_applied) AS total_spent
FROM orders AS o
WHERE payment_reject = "FALSE"
GROUP BY user_id
ORDER BY total_spent DESC
LIMIT 10
This gives the user_id, most expensive item they purchased (not counting shipping or discounts) as well as the total amount they spent on the site.
I was trying to use a nested query to generate a list of the second most expensive items they purchased, but keep getting errors. I've tried
SELECT user_id, MAX(item_total) AS second_highest
FROM orders
WHERE item_total < (SELECT user_id, SUM (item_total + shipping_cost -
discounts_applied) AS total_spent
FROM orders
WHERE payment_reject = "FALSE"
GROUP BY user_id
ORDER BY total_spent DESC
LIMIT 10)
group by user_id
I keep getting a row value misused error. Does anyone have pointers on this nested query or know of another way to find the second highest item purchased from within the group found in the first query?
Thanks!
(Note: The following assumes you're using Sqlite 3.25 or newer since it uses window functions).
This will return the second-largest item_total for each user_id without duplicates:
WITH ranked AS
(SELECT DISTINCT user_id, item_total
, dense_rank() OVER (PARTITION BY user_id ORDER BY item_total DESC) AS ranking
FROM orders)
SELECT user_id, item_total FROM ranked WHERE ranking = 2;
You can combine it with your original query with something like:
WITH ranked AS
(SELECT DISTINCT user_id, item_total
, dense_rank() OVER (PARTITION BY user_id ORDER BY item_total DESC) AS ranking
FROM orders),
totals AS
(SELECT user_id
, sum (item_total + shipping_cost - discounts_applied) AS total_spent
FROM orders
WHERE payment_reject = 0
GROUP BY user_id)
SELECT t.user_id, r.item_total, t.total_spent
FROM totals AS t
JOIN ranked AS r ON t.user_id = r.user_id
WHERE r.ranking = 2
ORDER BY t.total_spent DESC, t.user_id
LIMIT 10;
Okay, after fixing your table definition to better reflect the values being stored in it and the stated problem, and fixing the data and adding to it so you can actually get results, plus an optional but useful index like so:
CREATE TABLE orders (order_id INTEGER PRIMARY KEY
, user_id INTEGER
, item_total REAL
, shipping_cost NUMERIC
, discounts_applied NUMERIC
, payment_reject INTEGER);
INSERT INTO orders(user_id, item_total, shipping_cost, discounts_applied
, payment_reject) VALUES (9852,60.69,10,0,FALSE),
(2784,123.91,15,0,FALSE), (1619,119.75,15,0,FALSE), (9725,151.92,15,0,FALSE),
(8892,153.27,15,0,FALSE), (7105,156.86,25,0,FALSE), (4345,136.09,15,0,FALSE),
(7779,134.93,15,0,FALSE), (3874,157.27,15,0,FALSE), (5102,108.3,10,0,FALSE),
(3098,59.97,10,0,FALSE), (6584,124.92,15,0,FALSE), (5136,111.06,10,0,FALSE),
(1869,113.44,20,0,FALSE), (3830,129.63,15,0,FALSE), (9852,70.69,10,0,FALSE),
(2784,134.91,15,0,FALSE), (1619,129.75,15,0,FALSE), (9725,161.92,15,0,FALSE),
(8892,163.27,15,0,FALSE), (7105,166.86,25,0,FALSE), (4345,146.09,15,0,FALSE),
(7779,144.93,15,0,FALSE), (3874,167.27,15,0,FALSE), (5102,118.3,10,0,FALSE),
(3098,69.97,10,0,FALSE), (6584,134.92,15,0,FALSE), (5136,121.06,10,0,FALSE),
(1869,123.44,20,0,FALSE), (3830,139.63,15,0,FALSE);
CREATE INDEX orders_idx_1 ON orders(user_id, item_total DESC);
the above query will give:
user_id item_total total_spent
---------- ---------- -----------
7105 156.86 373.72
3874 157.27 354.54
8892 153.27 346.54
9725 151.92 343.84
4345 136.09 312.18
7779 134.93 309.86
3830 129.63 299.26
6584 124.92 289.84
2784 123.91 288.82
1619 119.75 279.5
(If you get a syntax error from the query now, it's because you're using an old version of sqlite that doesn't support window functions.)

Update multiple rows from select statement

I am trying to assign 'A' to [Student Details].group based on this SELECT statement.
SELECT TOP (10) PERCENT [Person Id], [Given Names], Surname, Gpa, [Location Cd]
FROM [Student Details]
WHERE ([Location Cd] = 'PAR')
ORDER BY Gpa DESC
I can't figure out how to use a SELECT statement in an UPDATE statement.
Can someone please explain how to accomplish this?
I am using ASP .NET and MsSQL Server if it makes a difference.
Thanks
I'm assuming you want to update these records and then return them :
SELECT TOP (10) PERCENT [Person Id], [Given Names], Surname, Gpa, [Location Cd]
INTO #temp
FROM [Student Details]
WHERE ([Location Cd] = 'PAR')
ORDER BY Gpa DESC
update [Student Details] set group='A' where [person id] in(select [person id] from #temp)
select * from #temp
I'm also assuming person id is the PK of student details
Try this using CTE (Common Table Expression):
;WITH CTE AS
(
SELECT TOP 10 PERCENT [Group]
FROM [Student Details]
WHERE ([Location Cd] = 'PAR')
ORDER BY Gpa DESC
)
UPDATE CTE SET [Group] = 'A'
Is this you want?
Update top (10) Percent [Student Details] set [group] = 'A'
where [Location Cd] = 'PAR' AND [group] is null

Error: ORA-00937

I want to create a table NEW_DEPTS. I have DEPARTMENT_ID and DEPARTMENT_NAME which is in DEPARTMENTS table.
desc departments
Name Null? Type
------------------------------- -------- ----
DEPARTMENT_ID NOT NULL NUMBER(4)
DEPARTMENT_NAME NOT NULL VARCHAR2(30)
MANAGER_ID NUMBER(6)
LOCATION_ID NUMBER(4)
My EMPLOYEES table contains:
desc employees
Name Null? Type
------------------------------- -------- ----
EMPLOYEE_ID NOT NULL NUMBER(6)
FIRST_NAME VARCHAR2(20)
LAST_NAME NOT NULL VARCHAR2(25)
EMAIL NOT NULL VARCHAR2(25)
PHONE_NUMBER VARCHAR2(20)
HIRE_DATE NOT NULL DATE
JOB_ID NOT NULL VARCHAR2(10)
SALARY NUMBER(8,2)
COMMISSION_PCT NUMBER(2,2)
MANAGER_ID NUMBER(6)
DEPARTMENT_ID NUMBER(4)
Now, I want to create a table NEW_DEPTS which should contain DEPARTMENT_ID and DEPARTMENT_NAME along with total SALARY that each Department has. Every department have certain number of employees, so, for department number 10, 20, 30, and so on, total Salary should be calculated.
My main query is:
create table new_depts as
select d.department_id,d.department_name,sum(e.salary) dept_sal
from employees e,departments d
where e.department_id = d.department_id;
I got an Error:
select d.department_id,d.department_name,sum(e.salary) dept_sal
*
ERROR at line 2:
ORA-00937: not a single-group group function
So, I googled it. I found that group function like sum, avg, max, min can't be used in select statement. I needed GROUP BY clause. So, I wanted to solve it individually. Therefore, I skipped the "create table..." statement and wrote:
select distinct d.department_id,d.department_name,sum(e.salary) dept_sal
from employees e,departments d
where e.department_id = d.department_id
group by department_id;
I got Error:
group by department_id;
*
ERROR at line 4:
ORA-00911: invalid character
Then I wrote:
select d.department_id,d.department_name,sum(e.salary) dept_sal
from employees e,departments d
where e.department_id = d.department_id
group by d.department_id;
I got Error:
select d.department_id,d.department_name,sum(e.salary) dept_sal
*
ERROR at line 1:
ORA-00979: not a GROUP BY expression
Then I wrote:
select d.department_id,d.department_name,sum(e.salary) dept_sal
from employees e,departments d
where e.department_id = d.department_id
group by department_id;
I got Error:
group by department_id
*
ERROR at line 4:
ORA-00918: column ambiguously defined
I know that its a "join". But not getting how should I place GROUP BY clause so that my GROUP FUNCTION may run correctly.
You need to group by all columns not in an aggregate function and since you have defined a table alias you must use that in your columns. The error ORA-00918: column ambiguously defined is because you have two columns named department_id so you must specify the table the department_id is from:
select d.department_id,
d.department_name,
sum(e.salary) dept_sal
from employees e
inner join departments d
on e.department_id = d.department_id
group by d.department_id, d.department_name;
You will notice that I altered the query to use ANSI JOIN syntax (INNER JOIN).

Resources