find missing value between to tables in sqlalchemy - python

I have two tables with a common field I want to find all the the
items(user_id's) which present in first table but not in second.
Table1(user_id,...)
Table2(userid,...)
user_id in and userid in frist and second table are the same.

session.query(Table1.user_id).outerjoin(Table2).filter(Table2.user_id == None)

This is untested as I'm still new to SQLAlchemy, but I think it should push you in the right direction:
table2 = session.query(Table2.user_id).subquery()
result = session.query(Table1).filter(Table1.user_id.notin_(table2))
my guess is this type of approach would result in the following SQL:
SELECT table1.* FROM table1 WHERE table1.user_id NOT IN (SELECT table2.user_id FROM table2)

Related

How to get a true/false response from sqlite [duplicate]

I have an SQLite database. I am trying to insert values (users_id, lessoninfo_id) in table bookmarks, only if both do not exist before in a row.
INSERT INTO bookmarks(users_id,lessoninfo_id)
VALUES(
(SELECT _id FROM Users WHERE User='"+$('#user_lesson').html()+"'),
(SELECT _id FROM lessoninfo
WHERE Lesson="+lesson_no+" AND cast(starttime AS int)="+Math.floor(result_set.rows.item(markerCount-1).starttime)+")
WHERE NOT EXISTS (
SELECT users_id,lessoninfo_id from bookmarks
WHERE users_id=(SELECT _id FROM Users
WHERE User='"+$('#user_lesson').html()+"') AND lessoninfo_id=(
SELECT _id FROM lessoninfo
WHERE Lesson="+lesson_no+")))
This gives an error saying:
db error near where syntax.
If you never want to have duplicates, you should declare this as a table constraint:
CREATE TABLE bookmarks(
users_id INTEGER,
lessoninfo_id INTEGER,
UNIQUE(users_id, lessoninfo_id)
);
(A primary key over both columns would have the same effect.)
It is then possible to tell the database that you want to silently ignore records that would violate such a constraint:
INSERT OR IGNORE INTO bookmarks(users_id, lessoninfo_id) VALUES(123, 456)
If you have a table called memos that has two columns id and text you should be able to do like this:
INSERT INTO memos(id,text)
SELECT 5, 'text to insert'
WHERE NOT EXISTS(SELECT 1 FROM memos WHERE id = 5 AND text = 'text to insert');
If a record already contains a row where text is equal to 'text to insert' and id is equal to 5, then the insert operation will be ignored.
I don't know if this will work for your particular query, but perhaps it give you a hint on how to proceed.
I would advice that you instead design your table so that no duplicates are allowed as explained in #CLs answer below.
For a unique column, use this:
INSERT OR REPLACE INTO tableName (...) values(...);
For more information, see: sqlite.org/lang_insert
insert into bookmarks (users_id, lessoninfo_id)
select 1, 167
EXCEPT
select user_id, lessoninfo_id
from bookmarks
where user_id=1
and lessoninfo_id=167;
This is the fastest way.
For some other SQL engines, you can use a Dummy table containing 1 record.
e.g:
select 1, 167 from ONE_RECORD_DUMMY_TABLE

SqlAlchemy Outer Join Only Returns One Table

So when I run
select * from table1 t1 left outer join table2 t2 on t1.id = t2.id; in sqlite3 terminal
I get the data back as I want and would expect.
However, when I run this in SqlAlchemy
TableOneModel.query.outerjoin(TableTwoModel,TableOneModel.id == TableTwoModel.id)
I only get table1 information back. I don't even get empty columns from table2. Am I missing something silly?
You're probably using Flask-SQLAlchemy, which provides the query property as a shortcut for selecting model entities. Your query is equivalent to
db.session.query(TableOneModel).\
join(TableTwoModel,TableOneModel.id == TableTwoModel.id)
Either explicitly query for both entities:
db.session.query(TableOneModel, TableTwoModel).\
join(TableTwoModel,TableOneModel.id == TableTwoModel.id)
or add the entity to your original:
TableOneModel.query.\
join(TableTwoModel,TableOneModel.id == TableTwoModel.id).\
add_entity(TableTwoModel)

What's the fastest way to see if a table has no rows in postgreSQL?

I have a bunch of tables that I'm iterating through, and some of them have no rows (i.e. just a table of headers with no data).
ex: SELECT my_column FROM my_schema.my_table LIMIT 1 returns an empty result set.
What is the absolute fastest way to check that a table is one of these tables with no rows?
I've considered: SELECT my_column FROM my_schema.my_table LIMIT 1 or SELECT * FROM my_schema.my_table LIMIT 1
followed by an if result is None(I'm working in Python). Is there any faster way to check?
This is not faster than your solution but returns a boolean regadless:
select exists (select 1 from mytable)
select exists (select * from myTab);
or
select 1 where exists (select * from myTab)
or even
SELECT reltuples FROM pg_class WHERE oid = 'schema_name.table_name'::regclass;
The 3rd example uses the estimator to estimate rows, which may not be 100% accurate, but may be a tad bit faster.
SELECT COUNT(*) FROM table_name limit 1;
Try this code .

How to get the ID of last updated row in a single UPDATE statement?

Suppose I have a table MyTable where the primary key is ID and a composite unique key is ColA and ColB.
I want to retrieve the ID affected by an UPDATE statement like this:
UPDATE MyTable
SET ColC='Blah'
WHERE ColA='xxx' and ColB='yyy'
Is there any way to do this using sqlite3 in python3 in a single statement without doing another SELECT after a successful UPDATE? I'm aware of lastrowid attribute on a cursor, but it seems to only apply to INSERTs.
More generally, I'm curious if any SQL engine allows for such functionality.
You asked if it could be done in some other DBMS, so I found this method in MySQL:
UPDATE MyTable as m1
JOIN (SELECT #id := id AS id
FROM MyTable
WHERE ColA = 'xxx' AND ColB = 'yyy') AS m2
ON m1.id = m2.id
SET m1.ColC = 'Blah';
After this you can do SELECT #id to get the ID of the updated row.

Updating a table from another table with multiple columns in sqlalchemy

I want to update multiple columns of one table according to other multiple columns of another table in SQLAlchemy. I'm using SQLite when testing it, so I can't use the `UPDATE table1 SET col=val WHERE table1.key == table2.key" syntax.
In other words, I'm trying to create this sort of update query:
UPDATE table1
SET
col1 = (SELECT col1 FROM table2 WHERE table2.key == table1.key),
col2 = (SELECT col2 FROM table2 WHERE table2.key == table1.key)
In SQLAlchemy:
select_query1 = select([table2.c.col1]).where(table1.c.key == table2.c.key)
select_query2 = select([table2.c.col2]).where(table1.c.key == table2.c.key)
session.execute(table.update().values(col1=select_query1, col2=select_query2))
Only I'd like to do the query only once instead of twice, unless SQLite and MySQL are smart enough not to make that query twice themselves.
I don't think you can. Thus, this is not really an answer, but it is far too long for a comment.
You can easily compose your query with 2 columns (I guess you already knew that):
select_query = select([table2.c.col1, table2.c.col2]).where(table1.c.key == table2.c.key)
and afterwards you can use the method with_only_columns(), see api:
In[52]: print(table.update().values(col1 = select_query.with_only_columns([table2.c.col1]), col2 = select_query.with_only_columns([table2.c.col2])))
UPDATE table SET a=(SELECT tweet.id
FROM tweet
WHERE tweet.id IS NOT NULL), b=(SELECT tweet.user_id
FROM tweet
WHERE tweet.id IS NOT NULL)
But as you see from the update statement, you will be effectivelly doing two selects. (Sorry I did not adapt the output completely to your example, but I'm sure you get the idea).
I'm not sure whether, as you say, MySQL will be smart enough to make it one query only. I guess so. Hope it helps anyway.

Categories