Sqlite Join confusion - sqlite

My first ever Stackoverflow question so go easy on me, I am not very experienced with SQLite.
I have a table of football teams
CREATE TABLE IF NOT EXISTS teams (
teamId INTEGER PRIMARY KEY NOT NULL,
name TEXT,
);
and a table of matches
CREATE TABLE IF NOT EXISTS matches (
matchId INTEGER PRIMARY KEY NOT NULL,
homeTeamId INTEGER,
awayTeamId INTEGER,
);
I am trying to work out the SELECT statement that would display the list of matches but would replace both the homeTeamId and the awayTeamId numbers with the team names.
I have tried several variants but because two fields in the matches table join back to the same teams table I am getting either syntax errors or ambiguous column errors.
Sorry for a fairly basic question, any help appreciated.
Geoff

Try this:
select m.matchId, h.name, a.name
from matches m
inner join teams h on h.teamId = m.homeTeamId
inner join teams a on a.teamId = m.awayTeamId
You have not posted the variants you have tried, so I just assume that you the problem was caused by not using aliases (in my example h and a) for the table teams. You have to use at least one alias, if you need to join one table twice.

Thanks for the speedy reply. In the typical way I stumbled on the solution about 15 minutes after I posted my question, my solution was identical to yours except that I didn't bother aliasing the matches table.
Your answer had a little typo in it I think
SELECT m.matchId, h.name, a.name
FROM matches m
INNER JOIN teams h ON h.teamId = m.homeTeamId
INNER JOIN teams a ON a.teamId = a.awayTeamId
-- ^ should be m.awayTeamId
But thanks again for your help!
Geoff

Related

Cant navigate into a specific column sqlite

The first link is the problems.
I am very inexperienced in SQLite and needed some help.
Thanks in advance!
https://imgur.com/v7BdVe3
These are all the tables displayed open
https://imgur.com/a/VMOxAuc
https://imgur.com/a/LrDcCBQ
The schema
https://imgur.com/a/bv5KTHN
This is as far as I could get which is close but I couldn't figure out how to sort it also by marina 1.
SELECT BOAT_NAME, OWNER.OWNER_NUM, LAST_NAME, FIRST_NAME from OWNER inner join MARINA_SLIP on OWNER.OWNER_NUM = MARINA_SLIP.OWNER_NUM;
If you know anything else bout the other questions feel free to help me with those too, Thanks!
I believe that you want
SELECT BOAT_NAME, OWNER.OWNER_NUM, LAST_NAME, FIRST_NAME
FROM OWNER INNER JOIN MARINA_SLIP ON OWNER.OWNER_NUM = MARINA_SLIP.OWNER_NUM
WHERE MARINA_NUM = 1
ORDER BY BOAT_NAME;
The second question involves multiple joins.
The third question asks you to use the count(*) function, noting that this is an aggregate function and will result in the number of rows for the GROUP as per the GROUP BY clause (if no GROUP BY clause then there is just the one GROUP i.e. all resultant rows).
The fourth question progresses a little further asking you to extend the GROUP BY clause with the HAVING clause (see link above for GROUP BY).

Efficient insertion of row and foreign table row if it does not exist

Similar to this question and this solution for PostgreSQL (in particular "INSERT missing FK rows at the same time"):
Suppose I am making an address book with a "Groups" table and a "Contact" table. When I create a new Contact, I may want to place them into a Group at the same time. So I could do:
INSERT INTO Contact VALUES (
"Bob",
(SELECT group_id FROM Groups WHERE name = "Friends")
)
But what if the "Friends" Group doesn't exist yet? Can we insert this new Group efficiently?
The obvious thing is to do a SELECT to test if the Group exists already; if not do an INSERT. Then do an INSERT into Contacts with the sub-SELECT above.
Or I can constrain Group.name to be UNIQUE, do an INSERT OR IGNORE, then INSERT into Contacts with the sub-SELECT.
I can also keep my own cache of which Groups exist, but that seems like I'm duplicating functionality of the database in the first place.
My guess is that there is no way to do this in one query, since INSERT does not return anything and cannot be used in a subquery. Is that intuition correct? What is the best practice here?
My guess is that there is no way to do this in one query, since INSERT
does not return anything and cannot be used in a subquery. Is that
intuition correct?
You could use a Trigger and a little modification of the tables and then you could do it with a single query.
For example consider the folowing
Purely for convenience of producing the demo:-
DROP TRIGGER IF EXISTS add_group_if_not_exists;
DROP TABLE IF EXISTS contact;
DROP TABLE IF EXISTS groups;
One-time setup SQL :-
CREATE TABLE IF NOT EXISTS groups (id INTEGER PRIMARY KEY, group_name TEXT UNIQUE);
INSERT INTO groups VALUES(-1,'NOTASSIGNED');
CREATE TABLE IF NOT EXISTS contact (id INTEGER PRIMARY KEY, contact TEXT, group_to_use TEXT, group_reference TEXT DEFAULT -1 REFERENCES groups(id));
CREATE TRIGGER IF NOT EXISTS add_group_if_not_exists
AFTER INSERT ON contact
BEGIN
INSERT OR IGNORE INTO groups (group_name) VALUES(new.group_to_use);
UPDATE contact SET group_reference = (SELECT id FROM groups WHERE group_name = new.group_to_use), group_to_use = NULL WHERE id = new.id;
END;
SQL that would be used on an ongoing basis :-
INSERT INTO contact (contact,group_to_use) VALUES
('Fred','Friends'),
('Mary','Family'),
('Ivan','Enemies'),
('Sue','Work colleagues'),
('Arthur','Fellow Rulers'),
('Amy','Work colleagues'),
('Henry','Fellow Rulers'),
('Canute','Fellow Ruler')
;
The number of values and the actual values would vary.
SQL Just for demonstration of the result
SELECT * FROM groups;
SELECT contact,group_name FROM contact JOIN groups ON group_reference = groups.id;
Results
This results in :-
1) The groups (noting that the group "NOTASSIGNED", is intrinsic to the working of the above and hence added initially) :-
have to be careful regard mistakes like (Fellow Ruler instead of Fellow Rulers)
-1 used because it would not be a normal value automatically generated.
2) The contacts with the respective group :-
Efficient insertion
That could likely be debated from here to eternity so I leave it for the fence sitters/destroyers to decide :). However, some considerations:-
It works and appears to do what is wanted.
It's a little wasteful due to the additional wasted column.
It tries to minimise the waste by changing the column to an empty string (NULL may be even more efficient, but for some can be confusing)
There will obviously be an overhead BUT in comparison to the alternatives probably negligible (perhaps important if you were extracting every Facebook user) but if it's user input driven likely irrelevant.
What is the best practice here?
Fences again. :)
Note Hopefully obvious, but the DROP statements are purely for convenience and that all other SQL up until the INSERT is run once
to setup the tables and triggers in preparation for the single INSERT
that adds a group if necessary.

Null values with all types of OUTER-JOIN is it me or is this normal? using Oracle db11g

I got a problem with something and I don't know if the thing I am doing is right.. or deadly wrong.
I am working with the outer-join concept. In my case with all the three of them. As I am typing my query's I get 50% viewable values en 50% null values. Is it normal to get this or are my query's wrong. I show you a couple of examples that I am working with.
Query 1. What I want to do is to get the names of the employees and address of the stores that they are working for.
select m.naam, w.adres, w.winkel_nummer
from medewerkers m, winkel w
where m.naam(+)= w.adres;
result:
Query 2. I want to get all the phone numbers. In this case it's from the employees and from the members.
select s.telefoon_nummer, l.telefoon_nummer
from medewerkers s
full outer join lid l on s.telefoon_nummer = l.telefoon_nummer;
result:
//note: with the full outer join I coudn't show the whole picture
The problem with both result are 'they are not combined'. Does that mean that I am writing a wrong query or is this normal?
I hope my question is not too vague. I cannot find the solution on the web
Thanks in advance
For #1, it looks like you're barking up the wrong tree.... why would you join the employee name to the address? That makes no sense.
select m.naam, w.adres, w.winkel_nummer
from medewerkers m, winkel w
where m.STOREKEYFIELD(+)= w.STOREKEYFIELD;
You have to join the two tables on the key for the store table to get anything meaningful back there.
For #2, if you just want a full list of phone #s from 2 tables, use UNION:
select s.telefoon_nummer
from medewerkers s
union
select l.telefoon_nummer
from lid l
There is no need to join anything unless you are expecting only things that match in both tables.

select * from (select...) sqlite python

I'm working on a sqlite database and try to make a special request between two tables.
In the first table (table1 for example), i have two columns named "reference" and "ID". I want to search an ID in it, get it value in "reference" and display all informations from the table which have this value as name.
I try to find something on the internet but I didn't find an answer.
This is the request I made:
select * from (select Reference from table1 where Name='Value1')
It only give me the result of
select Reference from table1 where Name='Value1'
EDIT:
I want
select Reference from table1 where Name='Value1' => name of table
select * from name of table => show all elements
I'm new in sqlite but I hope you can help me.
Thank you by advance
Matt
If I understand your question correctly, I don't think there's a way to do it in sql completely (or at least not in a portable way). I'd recommend one of 3 solutions:
Do exactly what you want, but do some processing in Python. That means query your master table, then construct new query based on each of the rows returned.
If you have many tables, possibly changing dynamically - it may be a good idea to rethink your database design. Maybe you can move some of the changing table names into a new column and put your data in one table?
If you have only a few tables available as the Reference and they never change, you could join all the possible tables, like:
SELECT ... FROM table1
LEFT JOIN table2
ON table1.id = table2.id AND table1.Reference = "table2"
LEFT JOIN table3 ...
But you may need to explain it all a bit better...

Sqlite : ambiguous column name

I'm a newbie and i try to do that on my database
SELECT id FROM import a INNER JOIN import b ON a.id-1 =b.id AND b.val =0 WHERE a.val=-1
Pb : ambiguous column name: id
My table :
CREATE TABLE "import" (
"id" INTEGER PRIMARY KEY NOT NULL ,
"id_analyse" integer,
"cross" varchar,
"date" datetime,
"close" double,
"low" double,
"high" double,
"T" integer DEFAULT (NULL) ,
"B" INTEGER
)
I can't understand because i read
When more than one table is used (in a JOIN for example) there may be two columns with the same name.
And i use only one table !
is there somebody who can help me ?
stephane
Just specify which id you want to select, e.g
SELECT a.id ....
Also your table does not seem to have the val column you're using later in the query.
You are actually using two tables in your query, not one, although they both get their data from the same underlying physical table. The tables are called a and b. In this particular query it doesn't matter whether you do SELECT a.id or SELECT b.id because the values are always the same. But imagine you wrote ON a.id = b.id + 1 -- in that it would make a difference whether you SELECTed the id column from a or b.
You may also get this error from an ambiguity in your WHERE clause. So, for example, instead of...
WHERE _id = 4
...you may need to put...
WHERE my_table_name._id = 4
I had a case where the error happened in sqlite for query:
select * from A, B where A.col=B.col
The problem was that the col was present in both the tables A and B.
This was fixed by specifically selecting all columns from table B: Select B.*...
Another option is to declare field alias using AS keyword in the query.
SELECT import.id AS id, id_analyse, any_other_field FROM import WHERE ...
This is especially useful when you use JOIN where id field most probably would be ambiguous in different tables. The downside of this approach is that you have to enumerate all the necessary fields in the query but in some cases this might be particularly useful.

Resources