Selecting words that end in 'n' in oracle sqlplus - sql

Select first names and last names of the table teachers where first names end in 'n'.
I wrote:
select first_name, last_name
from teachers
where type='teacher'
and last_name like '%n';
Unfortunately it selects no rows. It should select at least two.
The problem is with " last_name like '%n' " and I can't find a solution. Does anyone have any idea how i can solve this?Screenshot

The thing is, in your example there are no first_name columns that end with n. Yep.
Why? The the column type of first_name is CHAR instead of VARCHAR2, so Oracle fills up the column with spaces when each first name is shorter than 10 characters.
Solutions?
Use VARCHAR2 instead of CHAR as in:
create table teacher (
last_name varchar2(10), -- VARCHAR2 now!
first_name varchar2(10), -- VARCHAR2 now!
type varchar2(10)
);
With this structure your query will run well.
Alternatively, if you don't want to change the table structure, you can TRIM() the column, as in:
select first_name, last_name
from teachers
where type='teacher'
and trim(first_name) like '%n'; -- use TRIM here!

Try using. This will eliminate the chances of leftout of Case sensitive Data.
select first_name, last_name from teachers where lower(type)='teacher' and lower(first_name ) like '%n';

as per the screenshot the first_name, last_name columns have datatype as CHAR.
the thing about CHAR is that is appends spaces to reach its full length.
Example: for first_name CHAR(10) if u store 'Andra' it will be stored as 'Andra '
so use the trim function:
select first_name, last_name
from teachers
where type='teacher'
and trim(first_name) like '%n';
alternatively use the VARCHAR2 datatype instead of CHAR.
it does not append spaces at the end to reach its full length.

As you were told, your query should work. Problem is probably trivial (does case matters? Are there really lower case "n" letters in those names?).
Meanwhile, a few options for you:
SQL> select ename from emp
2 where ename like '%N';
ENAME
----------
ALLEN
MARTIN
SQL> select ename from emp
2 where substr(ename, -1) = 'N';
ENAME
----------
ALLEN
MARTIN
SQL> select ename from emp
2 where regexp_like(ename, 'N$');
ENAME
----------
ALLEN
MARTIN
SQL>
[EDIT: CHAR datatype issue]
SQL> create table empc (ename char(10));
Table created.
SQL> insert into empc select ename from emp;
12 rows created.
SQL> select ename from empc where ename like '%N';
no rows selected
SQL> select ename from empc where trim(ename) like '%N';
ENAME
----------
ALLEN
MARTIN
SQL>

If you have char data type then you should try trimming of space chars from your first_name values
select first_name, last_name
from teachers
where type='teacher'
and trim(first_name) like '%n';
anyway in your screeshot you have not teacher with firt_name endig with n ..try
select first_name, last_name
from teachers
where trim(first_name) like '%n';

You could try something like
SELECT *
FROM teachers a
WHERE TRIM (LOWER (a.first_name)) LIKE '%n';

Related

How to get length of string using Oracle query

In a table I have columns FIRST_NAME and LAST_NAME. I have to concatenate the two names and retrieve names containing more than 12 characters.
I tried the following query:
select *
from (select first_name, last_name
from customer as name
)
where length(NAME) = 12
Select *
from (
select first_name||last_name as name
from customer
)
where length(name)>12
You need only one SELECT
SELECT first_name || last_name AS name
FROM customer
WHERE LENGTH(first_name||last_name) > 12
Optionally TRIM name and last_name from spaces.
As an alternative, if you rewrite your question to check if the total length of first name and last name is more than 12, you probably get a different response from people with a more efficient code. It is not necessary to make Oracle actually concatenate the columns.
Programmers are too literal these days. :)
You are not concatenating the first name and last name.
Also no need to write an inline view, below is the query.
select FIRST_NAME || LAST_NAME as NAME
from CUSTOMER
where length(FIRST_NAME || LAST_NAME) > 12;

Find column values where first letter is upper case

I have a table EMP_INFO with EID, ENAME, GENDER. My objective is to display only those ENAME values where the first letter is Capital or uppercase.
Table like:
EID ENAME GENDER
001 Samuel M
002 john M
003 susan F
004 CALEB M
Desired output like:
EID ENAME
001 Samuel
004 CALEB
I have tried:
SELECT EID, ENAME
FROM EMP_INFO
WHERE ENAME like '[A-Z]%';
But this is just giving a blank output. No errors, no warnings but no output as well. Also I am using oracle sql developer.
Oracle does not support wildcards in the LIKE pattern. You can use regular expressions instead:
select EID , ENAME
from EMP_INFO
where regexp_like(ENAME, '^[A-Z]');
Alternatively, you could just compare the first character:
where substr(ENAME, 1, 1) BETWEEN 'A' AND 'Z'
Here is a working example of this version.
By default, Oracle is case-sensitive, so these should work on most Oracle systems.
We have a well-known function called initcap to be considerable :
SELECT EID, ENAME
FROM EMP_INFO
WHERE substr(ENAME,1,1) = substr(initcap(ENAME),1,1);
or alternatively use :
SELECT EID, ENAME
FROM EMP_INFO
WHERE ENAME between chr(65) and chr(92);
SQL Fiddle Demo
You might try something like the following (assuming you've not done anything to make your SQL queries case-insensitive):
SELECT eid, ename
FROM emp_info
WHERE ename >= 'A'
AND ename < CHR(ASCII('Z')+1);
This will ensure that the first character of ename falls between A and Z inclusive. The value of CHR(ASCII('Z')+1) is [ but that's not terribly important - I think it's clearer to use the functions in this case than the "magic character".
EDIT: The reason this works is that lower-case characters, as a group, appear after upper-case characters in many character sets*, so as long as a value of ename is between A and Z inclusive, according to the typical string comparison, it will start with an upper-case character.
*For example, here is the Unicode character table and here is the ASCII character table. I suspect that this solution may not work with EBCDIC character sets but I don't have a server handy on which I can confirm that suspicion.

Is there way to make SQL+ accept a parameter that isn't a number?

I'm stuck on this Homework problem for Oracle Plus, so any pointers in the right direction would be great. I need to...
"1.Create a script that will take an parameter of division(DIV) with script execution and generate employee report for all employee in this division."
Here's the layout of the relevant tables
Divisions
-Division_ID, Name
Employees2, Employee_ID, Division_ID, Job_ID, First_Name, Last_Name, Salary
So far I have
SET DEFINE '#'
SELECT Last_Name || ‘,’ || first_name AS Name, Divisions.Name
FROM Employees INNER JOIN Divisions
ON Employees2.Division_ID = Divisions.Divisions_ID
WHERE Division_ID = #v_Division_ID
It asks me for the division_id input but when i put it in it doesn't work. Now being that the Division_ID column isn't a number but rather an abbreviation like "SAL" for sales It seems that the error is because oracle plus wont take letters as input but rather only numbers? Is there a way to make this script so it accepts string/data that isn't numbers but rather something like "sal"?
When the substitution variable is being compared to a VARCHAR2, you want to enter the value you want to supply, e.g. 'SAL', with single quotation marks around it.
Here is an example from the SCOTT sample schema:
SCOTT#dev> SET DEFINE '#'
SCOTT#dev>
SCOTT#dev>
SCOTT#dev> SELECT e.ename employee_name
2 FROM emp e
3 INNER JOIN dept d
4 ON e.deptno = d.deptno
5 WHERE d.dname = #v_dname
6 /
Enter value for v_dname: 'SALES'
old 5: WHERE d.dname = #v_dname
new 5: WHERE d.dname = 'SALES'
EMPLOYEE_N
==========
ALLEN
WARD
MARTIN
BLAKE
TURNER
JAMES
6 rows selected.
Thus for you, you just need to enter 'SAL' for your #v_Division_ID.

Field Aliasing in queries, nzsql

I'm working in Netezza -- or, you know, pure data for Analytics -- nzsql, but I think this is an ANSI SQL question. The question is so basic, I don't even know how to search for it.
CREATE TEMPORARY TABLE DEMO1 AS SELECT 'SMORK' AS SMORK, 'PLONK' AS PLONK, 'SPROING' AS SPROING;
SELECT SMORK AS PLONK, PLONK, SPROING AS CLUNK, CLUNK
FROM DEMO1;
This returns 'SMORK, PLONK, SPROING, SPROING', which is to say, the query is fine reusing the CLUNK alias, but the PLONK alias is overwritten by the column from the source table. Now, if I really wanted the column from the source table, I could write SELECT SMORK AS PLONK, DEMO1.PLONK et c, but I don't know how to specify that I would prefer the alias I've defined earlier in same the SELECT clause.
Does anybody know a way?
In Netezza, when selecting a column, Netezza will search for table column first, and then alias.
Example:
Suppose we have the following statements:
CREATE TEMPORARY TABLE EMPLOYEES AS
SELECT 1001 AS EMPLOYEE_ID
,'Alex' AS FIRST_NAME
,'Smith' AS LAST_NAME
,'Alex J. Smith' AS FULL_NAME;
SELECT
EMPLOYEE_ID
,FIRST_NAME
,LAST_NAME
,LAST_NAME||', '||FIRST_NAME AS FULL_NAME
,'My full name is :'||FULL_NAME AS DESCRIPTION
FROM EMPLOYEES;
It will return
EMPLOYEE_ID FIRST_NAME LAST_NAME FULL_NAME DESCRIPTION
1001 Alex Smith Smith, Alex My full name is :Alex J. Smith
Notice in DESCRIPTION, the FULL_NAME value is picked from table column, not from alias.
If you want DESCRIPTION column use value from alias FULL_NAME, you can do it in two steps:
Step 1. Create a sub-query includes all columns you want. For all alias names you want to reuse, you need to name them as names not exist in any table columns on your FROM clause;
Step 2. SELECT only column you want from the subquery.
CREATE TEMPORARY TABLE EMPLOYEES AS SELECT 1001 AS EMPLOYEE_ID, 'Alex' AS FIRST_NAME, 'Smith' AS LAST_NAME, 'Alex J. Smith' AS FULL_NAME;
WITH EMPLOYESS_TMP AS (
SELECT
EMPLOYEE_ID
,FIRST_NAME
,LAST_NAME
,LAST_NAME||', '||FIRST_NAME AS FULL_NAME2
,FULL_NAME2 AS FULL_NAME
,'My full name is :'||FULL_NAME2 AS DESCRIPTION
FROM EMPLOYEES)
SELECT
EMPLOYEE_ID
,FIRST_NAME
,LAST_NAME
,FULL_NAME
,DESCRIPTION
FROM EMPLOYESS_TMP;
This will return what you want:
EMPLOYEE_ID FIRST_NAME LAST_NAME FULL_NAME DESCRIPTION
1001 Alex Smith Smith, Alex My full name is :Smith, Alex
Just change the order of your columns. Netezza tries to use your alias so you can either rename the column or change the order.
SELECT SMORK AS PLONK, PLONK, CLUNK, SPROING AS CLUNK
FROM DEMO1;

SQL, Displaying string instead of NULL/actual value

I'm working on an assignment and am having trouble with this question:
*Display the department name and the name of all employees plus their manager status. Status should show message ‘is a Manager’ for those who are managers. For those who are not managers show the message ‘is NOT a Manager’.
Include also empty departments as well, where the status value should be ‘NO Manager yet’
Display those people who are managers first followed by those whoa are NOT managers and empty departments last. Within those groupings sort by the employee name alphabetically.
Here is the heading sample.
Department Name Employee Manager Status*
I know NVL can be used to account for null values, but this question's stumped me.
The tables relevant to this question are:
emp:
Name Null Type
-------- -------- ------------
EMPNO NOT NULL NUMBER(4)
ENAME VARCHAR2(10)
JOB VARCHAR2(9)
MGR NUMBER(4)
HIREDATE DATE
SAL NUMBER(7,2)
COMM NUMBER(7,2)
DEPTNO NOT NULL NUMBER(2)
dept:
desc dept
Name Null Type
------ -------- ------------
DEPTNO NOT NULL NUMBER(2)
DNAME VARCHAR2(14)
LOC VARCHAR2(13)
If anyone could give me even a hint as to which function I could possibly use to display the strings, instead of the values I would be very greatful!
Depending of which database you use there is several ways to view strings instead of NULL results.
For your DB try look at NVL, NULLIF, NVL2, COALESCE, CASE-WHEN clauses (Oracle) or IIF function (Firebird/Interbase). I don't know which DB you use but most of these are common for most popular DBs.
Here is your hint: Use a CASE expression to assign values to your "Manager Status" column, something like:
CASE WHEN condition
THEN 'is a Manager'
ELSE 'is NOT a Manager'
END as Manager_Status
"condition" will be some value that, if "true" identifies a manager.