I have 2 tables (User, Order) in mysql with 1-n relationship b/w them where a user can have multiple orders.
So in order to fetch orders for each user I do a join b/w two tables like below
select user.id, order.item_name from user join `order` on user.id = order.user_id;
Here is the minimal sql with insert statements to reproduce this
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT,
`user_name` varchar(96) NOT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE `order` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int DEFAULT NULL,
`item_name` varchar(96) NOT NULL,
PRIMARY KEY (`id`),
KEY `ix_order_user_id` (`user_id`),
CONSTRAINT `order_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE
)
Here are the inserts
INSERT into user(user_name)
values ('user1'),
('user2'),
('user3'),
('user4'),
('user5'),
('user6'),
('user7');
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user1'), "apple");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user1'), "banana");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user1'), "orange");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user2'), "apple");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user2'), "orange");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user3'), "apple");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user3'), "banana");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user4'), "apple");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user5'), "orange");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user6'), "banana");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user7'), "banana");
INSERT into `order` (user_id, item_name) values ((select id from user where user.user_name = 'user7'), "grapes");
So the data set I have after above inserts is this
Items for user1 = ["apples", "oranges", "bananas"]
Items for user2 = ["apples", "oranges"]
Items for user3 = ["apples", "bananas"]
Items for user4 = ["apples"]
Items for user5 = ["oranges"]
Items for user6 = ["bananas"]
Items for user7 = ["bananas", "grapes"]
So the result set that I want from User table should be ordered like below
user4 # ["apples"]
user3 # ["apples", "bananas"]
user1 # ["apples", "oranges", "bananas"]
user2 # ["apples", "oranges"]
user6 # ["bananas"]
user7 # ["bananas", "grapes"]
user5 # ["oranges"]
Here is a simple demonstration of why the above ordering is correct
d = dict(user1=["apples", "oranges", "bananas"], user2=["apples", "oranges"], user3=["apples", "bananas"], user4=["apples"], user5=["oranges"], user6=["bananas"], user7=["bananas", "grapes"])
# User ordering without sorting item_names
for i in sorted(d, key=lambda k: d[k]):
print(f"{i}: {d[i]}")
user4: ['apples']
user3: ['apples', 'bananas']
user2: ['apples', 'oranges']
user1: ['apples', 'oranges', 'bananas']
user6: ['bananas']
user7: ['bananas', 'grapes']
user5: ['oranges']
# User ordering with sorted item_names
for i in sorted(d, key=lambda k: sorted(d[k])):
print(f"{i}: {d[i]}")
user4: ['apples']
user3: ['apples', 'bananas']
user1: ['apples', 'oranges', 'bananas']
user2: ['apples', 'oranges']
user6: ['bananas']
user7: ['bananas', 'grapes']
user5: ['oranges']
But I get the result in following when I join two tables and order by Order.item_name
for i in session.query(User).join(Order).order_by(Order.item_name).all():
items = [o.item_name for o in i.orders]
print(i.user_name, items)
# Result
user1 ['apple', 'orange', 'banana']
user3 ['banana', 'apple']
user4 ['apple']
user6 ['banana']
user7 ['banana', 'grapes']
user2 ['orange']
user5 ['orange']
So is there any way to achieve this with raw sql & with SQLAlchemy ?