Sqlite3 not matching rows with NULL values when using inclusion operator - sqlite

For some reason, sqlite3 is not matching rows that have a NULL value for a query that clearly should match it.
Say I have an employees table with two columns name and salary that has the following data:
sqlite> SELECT * FROM employees;
id name salary
--------------- --------------- ---------------
1 John Smith 10000
2 Mary Anderson 20000
3 David White NULL
Executing the following query results in:
sqlite> SELECT * FROM employees WHERE salary NOT IN (10000);
id name salary
--------------- --------------- ---------------
2 Mary Anderson 20000
Shouldn't I also expect row with id=3 to be in the list? Why isn't it on the list? I've been able to confirm this behavior in sqlfiddle.

You can't compare NULL to anything. There are IS NULL and IS NOT NULL operators in SQL to deal with it.
The proper query would be
SELECT *
FROM employees
WHERE salary NOT IN(50000)
OR salary IS NULL;
Here is SQLFiddle demo

Related

Joining two Tables in PL/SQL and obtain the required result

Structure of two tables in the database are as below.
1) Department table:
Dept_Id number(5) primary key,
Sept_Name varchar2(20),
Employee_strength number(4) not null.
2)Employee table:
E_Id number(5),
E_Name varchar2(20),
Designation varchar2(20),
D_ID number(5) references Department table Dept_ID.
A pl/sql program block to print the name the departments which has employees having the designation as "SE" is to be written and if no record in the department table fulfilling the given conditions found ,code should print the message "No record found" and if the record found code has to print Department name.
Please Help.
Here's one option (based on tables similar to yours; these belong to Scott).
I'll search for a SALESMAN.
SQL> break on deptno
SQL> select distinct d.deptno, e.job
2 from dept d left join emp e on e.deptno = d.deptno
3 order by d.deptno, e.job;
DEPTNO JOB
---------- ---------
10 CLERK
MANAGER
PRESIDENT
20 ANALYST
CLERK
MANAGER
30 CLERK
MANAGER
SALESMAN --> only department 30 has SALESMEN
40
10 rows selected.
SQL>
PL/SQL block:
SQL> set serveroutput on
SQL> declare
2 l_exists number(1);
3 begin
4 for cur_d in (select d.deptno, d.dname from dept d order by d.deptno) loop
5 select max(1)
6 into l_exists
7 from emp e
8 where e.deptno = cur_d.deptno
9 and e.job = 'SALESMAN';
10
11 dbms_output.put_line(cur_d.deptno || ' - ' ||
12 case when l_exists = 1 then cur_d.dname
13 else 'no record found'
14 end);
15 end loop;
16 end;
17 /
10 - no record found
20 - no record found
30 - SALES
40 - no record found
PL/SQL procedure successfully completed.
SQL>
If you want distinct department names then use the distinct() function in the SQL query.
I am using inner join to query the two table based on they have the same department id and department name is "SE".
Here are the steps to be followed:
declare the block(anonymous in this case)
write the SQL query for the cursor
begin the block
open the cursor
fetch the rows from the cursor
print the result
close the cursor
if the cursor doesn't contain any rows, so check for this condition
close the block
DECLARE
CURSOR C IS SELECT distinct(D.DEPT_NAME) FROM DEPARTMENTS D INNER JOIN EMPLOYEES E ON D.DEPT_ID = E.D_ID AND E.DESIGNATION LIKE 'SE';
RES C%ROWTYPE;
BEGIN
OPEN C;
loop
FETCH C INTO RES;
EXIT WHEN C%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(RES.DEPT_NAME);
end loop;
IF(C%ROWCOUNT=0) then
dbms_output.put_line('No record found');
end if;
END;
/

delete all rows if a field contains a value from another record

I've got a table like this:
Name Code
-------------------
John 1235
John 1235/11
John 1236/12
Mary 2500
Mary 2500/8
Mary 3600
Mary 3600/9
I want to delete all the rows where the value of code is contained in another row.
In the example I want to delete these records:
Name Code
-------------------
John 1235
Mary 2500
Mary 3600
Here is one method:
delete from t
where exists (select 1
from t t2
where t2.value like t1.value || '/%'
);
If you don't want to actually delete the records, but just want a query to not return them:
select *
from t
where not exists (select 1
from t t2
where t2.value like t1.value || '/%'
);
These assume that (as in the example), "is contained" really means "starts with before the "/".
Delete From tablename t
Where Exists
(Select * from table
Where charIndex(t.Code, Code) !=0)

Common Table Expression in sqlite using rowid

I found a good article on converting adjacency to nested sets at http://dataeducation.com/the-hidden-costs-of-insert-exec/
The SQL language used is Microsoft SQL Server (I think) and I am trying to convert the examples given in the article to sqlite (as this is what I have easy access to on my Macbook).
The problem I appear to be having is converting the part of the overall CTE query to do with the Employee Rows
EmployeeRows AS
(
SELECT
EmployeeLevels.*,
ROW_NUMBER() OVER (ORDER BY thePath) AS Row
FROM EmployeeLevels
)
I converted this to
EmployeeRows AS
(
SELECT
EmployeeLevels.*,
rowid AS Row
FROM EmployeeLevels
ORDER BY thePath
)
and the CTE query runs (no syntax errors) but the output I get is a table without the Row and Lft and Rgt columns populated
ProductName ProductID ParentProductID TreePath HLevel Row Lft Rgt
----------- ---------- --------------- ---------- ---------- ---------- ---------- ----------
Baby Goods 0 0 1
Baby Food 10 0 0.10 2
All Ages Ba 100 10 0.10.100 3
Strawberry 200 100 0.10.100.2 4
Baby Cereal 250 100 0.10.100.2 4
Beginners 150 10 0.10.150 3
Formula Mil 300 150 0.10.150.3 4
Heinz Formu 310 300 0.10.150.3 5
Nappies 20 0 0.20 2
Small Pack 400 20 0.20.400 3
Bulk Pack N 450 20 0.20.450 3
I think the start of the problem is the Row is not getting populated and therefore the Lft and Rgt columns do not get populated by the following parts of the query.
Are there any sqlite experts out there to tell me:
am I translating the rowid part of the query correctly
does sqlite support a rowid in a part of a CTE query
is there a better way? :)
Any help appreciated :)
am I translating the rowid part of the query correctly
No.
The SQL:
SELECT
EmployeeLevels.*,
rowid AS Row
FROM EmployeeLevels
ORDER BY thePath
has the Row defined as the rowid of table EmployeeLevels in SQLite, ignoring the order clause. Which is different from the intention of ROW_NUMBER() OVER (ORDER BY thePath) AS Row
does sqlite support a rowid in a part of a CTE query
Unfortunately no. I assume you mean this:
WITH foo AS (
SELECT * FROM bar ORDER BY col_a
)
SELECT rowid, *
FROM foo
but SQLite will report no such column of rowid in foo.
is there a better way?
Not sure it is better but at least it works. In SQLite, you have a mechanism of temp table which exists as long as your connection opens and you didn't delete it deliberately. Rewrite the above SQL in my example:
CREATE TEMP TABLE foo AS
SELECT * FROM bar ORDER BY col_a
;
SELECT rowid, *
FROM foo
;
DROP TABLE foo
;
This one will run without SQLite complaining.
update:
As of SQLite version 3.25.0, window function is supported. Hence you can use row_number() over (order by x) expression in your CTE if you happen to use a newer SQLite

Update field to zero in one table when data for the respective field is not present in the other table in sqlite

I am using SQLite. There are two tables shown below.
Transaction_Tbl
ID Name Credit/Debit Value
1 ABC credit 10
1 ABC credit 10
2 DEF credit 20
2 DEF debit 40
(record for third employee EFG not present in the table)
Based on the table, Emp_Tbl must be updated as below...
Emp_Table
ID Name Avg(Credit-Debit)
1 ABC 20
2 DEF -20
3 EFG 0 (as no records for EFG in Transaction_Tbl)
Now if there is a record for EFG in Transaction_Tbl for Debit, then in Emp_Tbl, the record for EFG must be negative (credit - debit => where credit must be taken as zero as no records for credit.).
How to do it?
Assuming there's a table names listing all names (else where would efg sprint out from?!), then something like...:
sqlite> create table trans (id smallint, name string, cord string, value int);
sqlite> insert into trans(id,name,cord,value) values(1,'abc','credit',10);
sqlite> insert into trans(id,name,cord,value) values(1,'abc','credit',10);
sqlite> insert into trans(id,name,cord,value) values(2,'def','credit',20);
sqlite> insert into trans(id,name,cord,value) values(2,'def','debit',40);
sqlite> select * from trans;
1|abc|credit|10
1|abc|credit|10
2|def|credit|20
2|def|debit|40
sqlite> create table names (name string);
sqlite> insert into names(name) values('abc');
sqlite> insert into names(name) values('def');
sqlite> insert into names(name) values('efg');
to create and populate the tables and check the main one, then
sqlite> select names.name, sum(case trans.cord when 'credit' then trans.value when 'debit' then -trans.value else 0 end) from names left outer join trans on names.name=trans.name group by names.name;
abc|20
def|-20
efg|0
seems roughly what you're after, right?

Display rows as columns in oracle 11g

Need your help in below, i have to achieve below target from my table.
EMP Table
Record Id EMP Id Emp Name Emp Dept
-------- ------- ------- --------
1 123 ABC Sales
2 - 231 PQR DEPT
I want output in below format
Record ID Table Name Column Name column Values
-------- ---------- ----------- -------------
1 EMP EMP Id 123
1 EMP Emp Name ABC
1 EMP EMP Dept Sales
Is this output possible, would be very thankful if someone can provide query with example
You could try something like this with a temporary table.
temp table schema
Record ID Table Name Column Name column Values
QUERY
BEGIN
FOR t IN (SELECT table_name,column_name
FROM all_tab_columns
WHERE table_name='MyTable' and owner='MySchema' and column_name<>'RecordId' ) LOOP
EXECUTE IMMEDIATE
'INSERT INTO temp_table SELECT RecordId,'''||t.table_name||''','''||t.column_name||''','||t.column_name||' FROM ' || t.table_name;
END LOOP;
COMMIT;
END;
/
SELECT *
FROM temp_table
ORDER BY "RecordId";

Resources