SQL, Displaying string instead of NULL/actual value - sql

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.

Related

Selecting words that end in 'n' in oracle sqlplus

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';

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.

What is the significance of 'ordinals' in an ORDER BY clause with CASE conditions

I have a 'names' tables with two columns: last_name, first_name
last_name first_name
--------- ----------
Basu Rohini
Khan Amartya
Nandy Upanita
Ghosh Shankha
NULL Claire
NULL Amelie
When I am doing (1st SQL):
SELECT last_name, first_name FROM names
ORDER BY
CASE
WHEN last_name IS NOT NULL THEN 3
ELSE 100
END,
last_name DESC
I'm getting an output:
last_name first_name
--------- ----------
Nandy Upanita
Khan Amartya
Ghosh Shankha
Basu Rohini
NULL Amelie
NULL Claire
But when I'm doing this (2nd SQL):
SELECT last_name, first_name from names
ORDER BY
CASE
WHEN last_name IS NOT NULL THEN 3
END,
last_name DESC
Or this (3rd SQL):
SELECT last_name, first_name from names
ORDER BY
CASE
WHEN last_name IS NOT NULL THEN 100
ELSE 3
END,
last_name DESC
I'm getting an output starting with last_name as NULL and first_name in ascending order, followed by the non-null last_names in descending order:
last_name first_name
--------- ----------
NULL Amelie
NULL Claire
Nandy Upanita
Khan Amartya
Ghosh Shankha
Basu Rohini
My questions:
Why is the 1st SQL giving an output with last_name sorted in a descending manner, for non-null last names?
Why I'm not getting an error in 1st SQL for 'CASE WHEN last_name IS NOT NULL THEN 3' saying 'Expressions 3 and last_name in ORDER BY clause are same'?
Why I was able to give any random numbers like 3 and 100, under the CASE statement? As per the SQL standard, this number can only be any non-negative integer value upto the degree of the number of columns. How is the integer within CASE statement working?
Those aren't ordinals - they're just numbers. Each of your CASE expressions essentially boils down to "assign all of the rows with a NULL last name <some fixed value> and all of the non-NULL last name rows <some other fixed value>" and then perform a sort on those fixed values.
So all that these CASE expressions do is ensure that all of the NULL rows will appear before/after the non-NULL rows. The specifics of which way around that is depends on the specific fixed values you're employing in each query.
Why is the 1st SQL giving an output with last_name sorted in a descending manner, for non-null last names?
Because that's what the second expression in your ORDER BY clause asks for?
Why I'm not getting an error in 1st SQL for 'CASE WHEN last_name IS NOT NULL THEN 3' saying 'Expressions 3 and last_name in ORDER BY clause are same'?
Because the expressions aren't the same, and even if they were, SQL doesn't prevent you from asking for redundant/pointless orderings (i.e. you can specify more expressions in an ORDER BY clause than are required to uniquely determine each rows final output position and no error is produced)
Why I was able to give any random numbers like 3 and 100, under the CASE statement? As per the SQL standard, this number can only be any non-negative integer value upto the degree of the number of columns. How is the integer within CASE statement working?
Because, again, these aren't ordinals. In order to be considered an ordinal, you have to supply a constant literal integer as the entire order by expression - not a larger expression, such as these CASE expressions.

SQL fundamentals practise select statement

I am preparing for the Oracle SQL Fundamentals I exam and am having trouble with this question:
Examine the structure of the EMP table:
Name Null? Type
EMPNO NOT NULL NUMBER(3)
ENAME VARCHAR2(25)
SALARY NUMBER(10,2)
COMM_PCT NUMBER(4,2)
I want to generate a report that fulfills the following requirements:
1. Displays employees' names and commission amounts
2. Excludes employees who do not have a commission
3. Displays a zero for employees whose SALARY does not have a value
You issue the following SQL statement:
SQL>SELECT ename, NVL(salary * comm_pct, 0)
FROM emp
WHERE comm_pct <> NULL;
What is the outcome?
ANSWER is It executes successfully but displays no result.
Why does nothing display though?
Also if you guys have any resources for good SQL fundamentals practise questions please let me know.
Be careful with nulls and comparisons. If you want rows where there is some data, you would have "WHERE comm_pct IS NOT NULL". Using the comparison operator <> with NULL will return nothing.
select * from dual where dummy <> NULL
is not the same as
select * from dual where dummy is not null;
The other stuff in the question is just a distraction from this point. You can't compare a NULL to something else (null really means "I don't know what the heck the value is").
Same thing with = comparison. You don't say "WHERE comm_pct = NULL", you say "WHERE comm_pct IS NULL".
As a reference, here's the online SQL Reference Guide. Here is the link that refers to NULLs and comparisons.

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;