SQLite, Filling in NULL with TEXT value - sqlite

I have a table with 2 columns and 9 Rows, FirstName and LastName.
All rows of FirstName Column IS NOT NULL, but 1 row of LastName is NULL.
How would I put a value into NULL?
This is the Code I have:
SELECT Emp1.FirstName Employee, Emp2.FirstName Manager
FROM Employee Emp1
LEFT JOIN Employee Emp2 ON Emp2.EmployeeID = Emp1.ReportsTo;
Which produces:
I have tried IFNULL, but it didn't seem to work.
SELECT Emp1.FirstName Employee, Emp2.FirstName Manager, IFNULL('No Manager')
FROM Employee Emp1
LEFT JOIN Employee Emp2 ON Emp2.EmployeeID = Emp1.ReportsTo;

The syntax for ISNULL is slightly different. Try this:
SELECT Emp1.FirstName Employee, IFNULL(Emp2.FirstName, 'No Manager') as Manager
FROM Employee Emp1
LEFT JOIN Employee Emp2 ON Emp2.EmployeeID = Emp1.ReportsTo;
Please let me know if I can help you further.

Related

Getting a min(date) AND max(date) AND their respective titles

I have three tables that I would like to select from
Table 1 has a bunch of static information about a user like their idnumber, name, registration date
Table 2 has the idnumber of the user, course number, and the date they registered for the course
Table 3 has the course number, and the title of the course
I am trying to use one query that will select the columns mentioned in table 1, with the most recent course they registered (name and date registered) as well as their first course registered (name and date registered)
Here is what I came up with
SELECT u.idst, u.userid, u.firstname, u.lastname, u.email, u.register_date,
MIN(l.date_inscr) as mindate, MAX(l.date_inscr) as maxdate, lc.coursename
FROM table1 u,table3 lc
LEFT JOIN table2 l
ON l.idCourse = lc.idCourse
WHERE u.idst = 12787
AND u.idst = l.idUser
And this gives me everything i need, and the dates are correct but I have no idea how to display BOTH of the names of courses. The most recent and the first.
And help would be great.
Thanks!!!
You can get your desired results by generating the min/max date_inscr for each user in a derived table and then joining that twice to table2 and table3, once to get each course name:
SELECT u.idst, u.userid, u.firstname, u.lastname, u.email, u.register_date,
l.mindate, lc1.coursename as first_course,
l.maxdate, lc2.coursename as latest_course
FROM table1 u
LEFT JOIN (SELECT idUser, MIN(date_inscr) AS mindate, MAX(date_inscr) AS maxdate
FROM table2
WHERE idUser = 12787
) l ON l.idUser = u.idst
LEFT JOIN table2 l1 ON l1.idUser = l.idUser AND l1.date_inscr = l.mindate
LEFT JOIN table3 lc1 ON lc1.idCourse = l1.idCourse
LEFT JOIN table2 l2 ON l2.idUser = l.idUser AND l2.date_inscr = l.maxdate
LEFT JOIN table3 lc2 ON lc2.idCourse = l2.idCourse
As #BillKarwin pointed out, this is more easily done using two separate queries.

SQLITE - Using results from a subquery in same query

I would like to know if, and if yes, how I could accomplsh the following:
Lets say I have two tables:
Table A has two Columns: id, name
Table B columns: owner, argument
Now I am trying to find in table A all rows with specific name (animal) and use their ids to find it's argument value in table b. Those argument values are different ids in table a. So as a result I would like to get two columns. first has the id of the items who has the specific name (animal) I am looking for and second column has the name of the item which has the id that is argument of the initial ids.
table a (example)
id || name
1 || animal
2 || animal
3 || animal
4 || animal
15 || cat
16 || dog
17 || horse
18 || bird
...
table b (example)
owner || argument
1 || 15
2 || 16
3 || 17
4 || 18
...
result (example)
id || name
1 || cat
2 || dog
3 || horse
4 || bird
Thanks in advance for any hints / help.
Andreas
You need a double join from tablea to tableb and again doublea:
select
a.name ownwename,
t.name name
from tablea a
inner join tableb b
on b.owner = a.id
inner join tablea t
on t.id = b.argument
where a.name = 'animal'
See the demo
I believe the following will do what you want
SELECT owner, name FROM tableb JOIN tablea ON argument = id;
However, as using a subquery you could use :-
SELECT owner, (SELECT name FROM tablea WHERE argument = id) AS name FROM tableb;
Working Example :-
DROP TABLE If EXISTS tablea;
CREATE TABLE IF NOT EXISTS tablea (id INTEGER PRIMARY KEY, name TEXT);
INSERT INTO tablea (name) VALUES ('animal'),('animal'),('animal'),('animal'),('cat'),('dog'),('horse'),('bird'),
('animal'),('cat'),('dog'),('horse'),('bird'),('animal'),
('cat'),('dog'),('horse'),('bird') -- id's 15-18 inclusive
;
DROP TABLE IF EXISTS tableb;
CREATE TABLE IF NOT EXISTS tableb (owner INTEGER PRIMARY KEY, argument INTEGER);
INSERT INTO tableb (argument) VALUES(15),(16),(17),(18);
SELECT owner, name FROM tableb JOIN tablea ON argument = id;
SELECT owner, (SELECT name FROM tablea WHERE argument = id) AS name FROM tableb;
Results :-
and the second

Column Relationships

I realize i'm far off the solution with what i have:
Select FirstName || ' ' || LastName AS Manager From Employee
Where (Select COUNT(ReportsTo) from Employee
group by ReportsTo
order by ReportsTo desc);
ReportsTovalues are the EmployeeID they report to
What i want is to query the name of the employee with the most Employees reporting to them and who they in turn report to without nulls. I'm Not sure how to make the connections between columns values such as ReportsTo to EmployeeID so any explanation would help
For Example the output i would want is two columns say | Fred Jones | Mary Anne| the first being the employee with the most reportsTo with the same value as their EmployeeID and the second being the name of the employee with the same EmployeeID as the first employees ReportTo
Do this step by step:
First step: Count how many employees report to a person.
select reportsto, count(*) from employee group by reportsto;
We can order this result by count(*) and limit it to only get one row, so as to get the person with the most reporters. Only problem is: What to do in case of ties, i.e. two persons have the same highest amount of reporters? SQLite doesn't offer much to help here. We'll have to query twice:
select reportsto
from employee
group by reportsto
having count(*) =
(
select count(*)
from employee
group by reportsto
order by count(*) desc
limit 1
);
Next step: Get the name. That means we must access the table again.
select
firstname || ' ' || lastname as manager
from employee
where e1.employeeid in
(
select reportsto
from employee
group by reportsto
having count(*) =
(
select count(*)
from employee
group by reportsto
order by count(*) desc
limit 1
)
);
Last step: Get the persons our found managers themselves report to. These can be many, so we group by manager and concatenate all those they report to.
select
e1.firstname || ' ' || e1.lastname as manager,
group_concat(e2.firstname || ' ' || e2.lastname) as reportsto
from employee e1
join employee e2 on e2.employeeid = e1.reportsto
where e1.employeeid in
(
select reportsto
from employee
group by reportsto
having count(*) =
(
select count(*)
from employee
group by reportsto
order by count(*) desc
limit 1
)
)
group by e1.firstname || ' ' || e1.lastname;
SELECT e.ReportsTo AS TopManagersEmployeeId, COUNT(e.ReportsTo) AS ReportedBy, m.FirstName + ' ' + m.LastName AS TopManagersName, mm.FirstName + ' ' + mm.LastName AS TheirManagersName FROM Employees e
JOIN Employees m
ON e.ReportsTo = m.EmployeeID
JOIN Employees mm
ON m.ReportsTo = mm.EmployeeID
GROUP BY e.ReportsTo, m.FirstName, m.LastName, mm.FirstName, mm.LastName
Once you have this data, you can do TOP 1 etc. You can also play around with JOIN, and make it INNER JOIN in the second set where Manager's Manager (mm) is being retrieved.

Deleting rows not existing in another table with composite primary key's

I'm using SQLite and are trying to move old rows from a table Students to Students_Old, and copy new rows from Students_Import.
The problem is I have multiple primary keys as this:
CREATE TABLE "Students" (
`LastName` TEXT NOT NULL,
`FirstName` TEXT NOT NULL,
`BornDate` TEXT NOT NULL,
`Class` TEXT NOT NULL,
`Photo` TEXT,
`ValidUntil` CHAR(10),
PRIMARY KEY(LastName,FirstName,BornDate))
All tables have this structure (except Students_Import that's missing Photo and ValidUntil).
So far I have managed to copy the old rows with this:
INSERT INTO Students_Old
SELECT DISTINCT a.LastName, a.FirstName, a.BornDate, a.Class, a.Photo, a.ValidUntil FROM
Students a LEFT JOIN Students_Import b ON a.LastName =b.LastName AND a.FirstName=b.FirstName AND a.BornDate=b.BornDate WHERE b.LastName is NULL;
And add the new rows with this:
INSERT INTO Students
SELECT DISTINCT a.LastName, a.FirstName, a.BornDate, a.Class, "", "" FROM
Students_Import a LEFT JOIN Students b ON a.LastName =b.LastName AND a.FirstName=b.FirstName AND a.BornDate=b.BornDate WHERE b.LastName is NULL
But I can't figure out how to delete old rows in Students (that don't exist in Students_Import).
I have tried a few variants of this:
DELETE FROM Students WHERE (LastName, FirstName, BornDate) IN
(SELECT DISTINCT a.LastName, a.FirstName, a.BornDate, a.Class, a.Photo, a.ValidUntil FROM
Students a LEFT JOIN Students_Import b ON a.LastName =b.LastName AND a.FirstName=b.FirstName AND a.BornDate=b.BornDate WHERE b.LastName is NULL);
But I only get syntax error or that I can't use it on multiple rows.
I would appreciate any help!
IN does not work with multiple columns.
To find rows that do not exist in another table, use NOT EXISTS with a correlated subquery:
DELETE FROM Students
WHERE NOT EXISTS (SELECT 1
FROM Students_Import
WHERE Students_Import.LastName = Students.LastName
AND Students_Import.FirstName = Students.FirstName
AND Students_Import.BornDate = Students.BornDate);
I don't think you can have multiple columns in the IN clause.
How about:
DELETE Students FROM Students s LEFT JOIN Students_Import si ON (s.LastName = si.LastName AND s.FirstName = si.FirstName AND s.BornDate = si.BornDate) WHERE s.LastName IS NULL;

SQlite how to display employee and manager names in this table?

I am new to SQLite. I want to display the name of each employee and his/her manager's name. But I am a little confused about how to link the managerID with EmployeeID? Do I need to use subquery?
table: Employee
Columns: EmployeeID [pk], EmployeeName, ManagerID
Like:
EmployeeID EmployeeName ManagerID
1 Alice 2
2 Peter null
3 John 2
4 Mary 1
means Peter is Alice and John's manager and Alice is Mary's manager.
SELECT EmployeeName AS Employee, EmployeeName AS Manager
FROM Employee
WHERE
You need to join the table on itself with a LEFT OUTER join. Since the boss won't have a manager (null), use 'ifnull':
select A.EmployeeName as 'EmployeeName',
ifnull(B.EmployeeName, 'BOSS') as 'ManagerName'
from employee A left outer join employee B
on A.managerId = B.employeeId;

Resources