join table with limit in sqlalchemy - sqlalchemy

Each user may have more than 1 address. I would like to limit users and extract all addresses by user_id.
user_ids = session.query(User.user_id).limit(10).all()
address_ids = session.query(Address).filter(Address.user_id.in_(user_ids)).all()
How can I do it in one query?

I recommend you to use subquery.
sub_query = session.query(User.user_id).limit(10).subquery()
address_ids = session.query(Address).filter(Address.user_id.in_(sub_query)).all()

Related

mysql check multiple column in on statement

I am stuck in 1 left join query in which I want to check multiple columns in on statement.
By default in the database, some column is null which I want to check in the on statement.
Now the issue is when I run a query using the OR operator it only runs the 1st condition and the rest are skipped.
If I use AND operator it throws an error.
So is there any way to get data from multiple conditions?
Here is my query:
$data = "SELECT
b.book_name, b.book_id,
b.cats_id, b.cats_id1,
b.cats_id2, b.cats_id3,
b.cats_id4, b.cats_id5,
b.cats_id6,
b.book_rating,
b.book_author,
b.book_stock,
b.book_publisher,
b.book_front_img,
b.book_status,
p.publisher_id,
p.publisher_name,
a.author_id,
a.author_name,
cat.cats_id,
cat.cats_name,
cat.cats_status
FROM
`books` AS b
LEFT JOIN `publisher` AS p
ON b.book_publisher = p.publisher_id
LEFT JOIN `author` AS a
ON b.book_author = a.author_id
LEFT JOIN categorys As cat
ON b.cats_id = cat.cats_id
OR b.cats_id1 = cat.cats_id
OR b.cats_id2 = cat.cats_id
OR b.cats_id3 = cat.cats_id
OR b.cats_id4 = cat.cats_id
OR b.cats_id5 = cat.cats_id
OR b.cats_id6 = cat.cats_id
GROUP BY
b.book_name
HAVING
cat.cats_name = '$search_data'
AND b.book_status = 1
ORDER BY
$sorting
LIMIT $offset, $page_limit"
You probably don't have more than one author displayed for your multi-author books either. You are misusing MySQL's notorious nonstandard extension to GROUP BY.
To troubleshoot this kind of query, disable that extension with SET sql_mode = CONCAT_WS(',',##sql_mode, 'ONLY_FULL_GROUP_BY'), then try your query again. You'll need more terms in your GROUP BY clause.
It looks like each books row has multiple category id columns. And it looks like you want to display information from your categorys table for each of them.
Use GROUP BY b.book_id, p.publisher_id, a.author_id, cats.cats_id to prevent MySQL's bizarro handling of GROUP BY from concealing your data.
I must add this: your multiple books.cats_id columns are not the SQLish way to handle your many-to-many relationship between books and categories. In the parlance of our trade, your books table is denormalized.
What you want is a new table called books_categorys with two columns, book_id and cats_id. It's called a join table. When a row is present in that table, it means a particular book is in a particular category. It's the SQLish way of handling a setup where each book can be in zero or more categorys. Here's an explanation. MySQL join many to many single row
Then you remove all the cats_id columns from books, and retrieve the categories like this.
Then you do something like this SELECT to get the categories.
SELECT books.id, books.name,
categorys.cats_id, categorys.cats_name, categorys.cats_status
FROM books
JOIN books_categorys ON books.book_id = books_categorys.book_id
JOIN categorys ON books_categorys.cats_id = categorys.cats_id
``

How do I put a previous result into the next query? MYSQL

Okay so, this is my query.
select id from rooms where owner = 'oknow';
and the answer I get is
325
However, I made another SQL within this one as below
update users set home_room = 'mysql_fetch_assoc()' where username = 'omarisgod';
I want the 'mysql_fetchassoc()' to be the '325' value, how do I do this?
A subquery will do this:
UPDATE users SET home_room = (SELECT id FROM rooms WHERE owner = 'oknow') WHERE username = 'omarisgod';
You can conceptualize it thusly: The query inside parentheses will return a result, which will be utilized by the outer query.

Using COUNT and NOT IN to find total results

Here's my current query I'm using
SELECT *
FROM accounts
WHERE source = 0
AND account_id NOT IN(SELECT receive FROM actions WHERE follow = '$account')
AND status = 0
ORDER BY RAND() LIMIT
I want to somehow do something like this
SELECT *
FROM accounts
WHERE source = 0
AND account_id NOT IN(SELECT * FROM actions WHERE follow = '$account')
AND COUNT((SELECT * FROM actions WHERE follow = '$account')) AS `total_received_follows`
AND total_received_follows < max_follows
AND status = 0
ORDER BY RAND() LIMIT
I basically need to get COUNT the amount of rows that have a follow value of '$account' from the actions table I then want to check this value has a lower value than the row max_follows from the accounts table
I understand that's probably not the correct syntax, but is their anyway I can do something like that using the query I have?
I'm a little confused, but here goes... In your second query, you're looking for accounts that don't have any corresponding rows in actions? But it also looks like you're trying to find accounts that have less than max_follows rows in actions. Am I right? You realise this is contradictory?
Regardless, this might be a place to start:
SELECT acc.*, COUNT(act.id) act_count FROM accounts acc
LEFT JOIN action act ON act.follow = acc.id
WHERE ...
GROUP BY acc.id
HAVING act_count < acc.max_follows

Codeigniter - convert mysql query to CodeIgniter's active record query

I'm trying to convert this SQL query into a codeigniter query
SELECT
uploads.EMAIL
FROM
uploads
JOIN (
SELECT EMAIL, COUNT(*) as num FROM uploads GROUP BY EMAIL
) c ON uploads.EMAIL = c.EMAIL
ORDER BY
c.num DESC,
EMAIL ASC
Thanks for the help
kind regards
I am not sure why you can't figure this out yourself using the active record documentation, but:
$this->db->select('uploads.EMAIL');
$this->db->from('uploads');
$this->db->join('(SELECT EMAIL, COUNT(*) as num FROM uploads GROUP BY EMAIL) c','uploads.EMAIL = c.EMAIL','',FALSE);
$this->db->order_by('c.num desc, uploads.EMAIL asc');
and then
$query = $this->db->get();
FYI, passing FALSE as the fourth parameter to the db->join() method will cause it not to escape the statement, so you should be careful if you're going to take external variables. This is, until CodeIgniter 3, the only way to do subqueries with active record without extending the active record class to add them.

mysql find only unique records in a subquery and show the count

i have two tables i am trying to get information from.
login table - which has the list of employees
projects table - which has the projects
in short, i am trying to write a query that will select the copywriters and perform a subquery on each that will return a field dubbed 'open_projects'. This, i can get to work with the below sql:
select web_login_id,
(select count(project_web_id) from project
where copywriter = web_login_id
and (`status` = 'open' or `status` = 'qual')) as open_projects from login
where roles like '%copywriter%'
and tierLevel like '%c1%'
order by open_projects asc
This returns something like:
1982983 3
1982690 22
2987398 5
The problem with this is that sometimes 5 or 6 of the projects will belong to the same client and are not actually being worked on as they are dealt with in a queue-ish fashion.
My question is how to modify the above sql so that the subquery will GROUP subset based on the client_login_id field.
This sql gives me an error of : subquery returns more than 1 row
select web_login_id,
(select count(project_web_id) from project
where copywriter = web_login_id
and (`status` = 'open' or `status` = 'qual') group by client_login_id) as open_projects from login
where roles like '%copywriter%'
and tierLevel like '%c1%'
order by open_projects asc
You need to rephrase this as an explicit join. I think the following does the trick:
select web_login_id, cw.open_projects
from login l left outer join
(select copywriter, count(project_web_id) as open_projects
from project
where `status` in ('open', 'qual')
group by copywriter
) cw
on l.web_login_id = cw.copywriter
where l.roles like '%copywriter%' and l.tierLevel like '%c1%'
order by open_projects asc
I'm not sure what the "group by client_login_id" is doing. It doesn't seem necessary.
Once you've done this, you can return as many columns as you like from the subquery.