PL/SQL select null value with other value - plsql

I have two columns, one is type and other is Id, i want to fetch all the records whose id is null for all the types except when type = 'Started', means when type is 'Started' then it should display the records without checking Id, in other types it will display only those records whose Id is null. any help?

I think you mean something like:
WITH your_table AS (SELECT 1 ID, 'started' TYPE FROM dual UNION ALL
SELECT NULL ID, 'finished' TYPE FROM dual UNION ALL
SELECT 2 ID, 'finished' TYPE FROM dual UNION ALL
SELECT NULL ID, 'started' TYPE FROM dual UNION ALL
SELECT 3 ID, 'started' TYPE FROM dual UNION ALL
SELECT 4 ID, 'progressing' TYPE FROM dual)
SELECT *
FROM your_table
WHERE (ID IS NULL AND TYPE != 'started')
OR TYPE = 'started'
ORDER BY TYPE, ID;
ID TYPE
---------- -----------
finished
1 started
3 started
started

I think this where clause is just fine:
where type = 'Started' or (type <> 'Started' and id is null)
Also, this query belongs to SQL and not PL/SQL which is a procuedre language.

Related

Always return all row, even when query has no result

I have a "tt_Results" table which contains exactly three row / ID like:
ID | ResultType
---------------
1 | first
1 | second
1 | third
My query looks like:
select t.resultType
from tt_Results
where ID = 1;
Normally, this query should return all the three row. My problem is if one or more row not exist I must union all the three "type".
select res.* from
(
select resultType, '1' as exists
from tt_Results
where ID = 1
union all
select 'first' resulttype, '0' as exists
from dual
where not exists (
select resulttype
from tt_Results
where resulttype = 'first' and ID = 1)
union all
select 'second' resulttype, '0' as exists
from dual
where not exists (
select resulttype
from tt_Results
where resulttype = 'second' and ID = 1)
union all
select 'third' resulttype, '0' as exists
from dual
where not exists (
select resulttype
from tt_Results
where resulttype = 'third' and ID = 1)
) res
The final query result looks good but it is very slow. Anyone have a better PL/SQL solution for it? Thanks for the answers!
Left join to your table from a table of all types, using a case to calculate exists based on whether a join was made or not:
select
type,
case when resultType is null then '0' else '1' end as exists
from (select 'first' type from dual union
select 'second' from dual union
select 'third' from dual) t
left join tt_Results on resultType = type
and ID = 1
Note that the condition ID = 1 is part of the join condition, not in a where clause.
I recommend creating a 3-row table for the types, then the query would become simply:
select
type,
case when resultType is null then '0' else '1' end as exists
from types
left join tt_Results on resultType = type
and ID = 1
You can do this by creating a subquery to hold the result types you're interested in, and then using a partitioned outer join, like so:
with tt_results as (select 1 id, 'first' resulttype from dual union all
select 1 id, 'second' resulttype from dual union all
select 1 id, 'third' resulttype from dual union all
select 2 id, 'second' resulttype from dual union all
select 2 id, 'third' resulttype from dual union all
select 3 id, 'first' resulttype from dual),
dummy as (select 1 position, 'first' resulttype from dual union all
select 2 position, 'second' resulttype from dual union all
select 3 position, 'third' resulttype from dual)
select res.id,
d.resulttype,
case when res.resulttype is not null then 1 else 0 end res_exists
from dummy d
left outer join tt_results res partition by (res.id) on d.resulttype = res.resulttype
order by res.id,
d.position;
ID RESULTTYPE RES_EXISTS
---------- ---------- ----------
1 first 1
1 second 1
1 third 1
2 first 0
2 second 1
2 third 1
3 first 1
3 second 0
3 third 0
Adrian Billington has produced an excellent article on partititioned outer joins if you want to learn more about them.
If your tt_results table could contain more resulttypes than you're interested in, you might want/need to add a predicate to only grab the rows from the dummy subquery, otherwise you could get ids where all 3 resulttypes don't exist (although that may be what you want to see).
ETA: This will work if you need to select multiple ids in one go.

Conversion failed when converting character string to smalldatetime data type

SELECT B.Value
FROM table1 A WITH (NOLOCK)
INNER JOIN table2 B WITH (NOLOCK) ON A.id = B.id
WHERE
A.Name = 'COMPLETED_AT'
AND CONVERT(smalldatetime, A.Value) < GETDATE() - 30
AND B.Name = 'RESULT'
Getting error message
Conversion failed when converting character string to smalldatetime data type
when executing the above query
Example table structure
ID Name Value
1 Result R12344
1 Completed_At 2015-03-20T06:06:46
2 Result R23445
2 Completed_At 2014-03-20T06:06:46
Column value is of nvarchar(400) datatype
The query result should display the values of result name type which have been made an entry of more than 30 days.
Looking forward in hearing from you.
Avoid Null In Datetime Coloumn field & fix this error (Conversion failed when converting character string to smalldatetime data type.):
First, I give this type get this error:
select * from Tabel1 where ISNULL(Datecoloumn1,**'0'**)!='1900-01-01 00:00:00'
The single quotation Zero is the Problem
I fix like this method :
select * from Tabel1 where ISNULL(Datecoloumn1,**0**) != '1900-01-01 00:00:00'
It works just fine, just changed Table2 to Table1, because you said is a self join.
CREATE TABLE Table1
([ID] int, [Name] varchar(12), [Value] varchar(19))
;
INSERT INTO Table1
([ID], [Name], [Value])
VALUES
(1, 'Result', 'R12344'),
(1, 'Completed_At', '2015-03-20T06:06:46'),
(2, 'Result', 'R23445'),
(2, 'Completed_At', '2014-03-20T06:06:46')
;
SELECT B.Value
FROM table1 A WITH (NOLOCK)
INNER JOIN table1 B WITH (NOLOCK) ON A.id = B.id
WHERE
A.Name = 'COMPLETED_AT'
AND CONVERT(smalldatetime, A.Value) < GETDATE() - 30
AND B.Name = 'RESULT'
Result
Value
R23445

Merge/Insert Statement ORA-911

Below statement generate "ORA-00911: invalid character" issue in ORACLE while migration where as it works fine directly inside AQT/SQL Developer.
INSERT INTO ss.CODETBL(FIELDNAME,FIELDVALUE,IDS)
SELECT FIELDNAME,FIELDVALUE,IDS FROM
(
SELECT 'ACCT_TYPE_CD' FIELDNAME, '$' FIELDVALUE,'SAMP' IDS FROM DUAL UNION ALL
SELECT 'ACCT_TYPE_CD', 'L','SAMP' FROM DUAL UNION ALL
SELECT 'ACCT_TYPE_CD', 'C','SAMP' FROM DUAL
)
D
WHERE NOT EXISTS
(
SELECT 1 FROM SS.CODETBL
WHERE D.FIELDNAME = FIELDNAME
AND D.FIELDVALUE = FIELDVALUE
AND D.IDS = IDS
);

Return an empty row with the necessary columns with NULL value

I need to transform the following expression for SQLite, any idea how to do this?
IF EXISTS (SELECT [ID] FROM [USERS] WHERE [ID]=1)
SELECT [ID], [NAME], [CITY] FROM [USERS] WHERE [ID]=1
ELSE
SELECT NULL AS ID, NULL AS NAME, NULL AS CITY
UNION ALL
IF EXISTS (SELECT [ID] FROM [USERS] WHERE [ID]=2)
SELECT [ID], [NAME], [CITY] FROM [USERS] WHERE [ID]=2
ELSE
SELECT NULL AS ID, NULL AS NAME, NULL AS CITY
In other words, I need to return an empty row with the necessary columns with NULL value, when the condition does not meet criteria.
You could create a virtual table of all the IDs you want, and then use a left outer join to get the matching Users record values or NULL:
SELECT Users.*
FROM (SELECT 1 AS ID
UNION ALL
SELECT 2) AS IDList
LEFT JOIN Users ON IDList.ID = Users.ID
SQLite has no IF statement, or any other control flow statement.
What you could do is to take the actual record (if it exists) and the NULL record together, and then take only the first one:
SELECT * FROM (SELECT ID, Name, City FROM Users WHERE ID = 1
UNION ALL
SELECT NULL, NULL, NULL
LIMIT 1)
UNION ALL
SELECT * FROM (SELECT ID, Name, City FROM Users WHERE ID = 2
UNION ALL
SELECT NULL, NULL, NULL
LIMIT 1)

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