I'm trying to create a relationship between between two tables, Accounts and
Items:
class Account(Base):
__tablename__ = 'accounts'
account_id = Column(Integer, primary_key=True)
item_order = Column(ARRAY(Integer))
items = relationship(?)
class Item(Base):
item_id = Column(Integer, primary_key=True)
account_id = Column(Integer, ForeignKey('accounts.account_id'))
When I get all items for an account, they need to be in order. The order is stored in "item_order" on accounts, otherwise assumed to be ordered by item_id.
Here's is how I'd query all of the items for an account:
SELECT * FROM accounts A INNER JOIN items T USING (account_id)
WHERE A.account_id=1
ORDER BY
CASE WHEN A.item_order IS NOT NULL THEN nullif(idx(A.item_order, T.item_id::int), 0)
ELSE
T.item_id
END
NULLS LAST;
Is it possible to get this into an SQLAlchemy relationship?
Related
Is it possible to connect multiple tables to single table with 2 foreign keys?
My tables:
const Products = sequelize.define("Products", {name: sequelize.STRING});
const Categories = sequelize.define("Categories ", {name: sequelize.STRING});
const Translations = sequelize.define("Translations ", {name: sequelize.STRING});
I want to connect Translations table to Products and Categories with foreign keys
'object_id' (object_id = product_id or category_id) and 'object_type' ( object_type= 'products' or 'categories');
The mysql queries I aim:
SELECT *
FROM Translations t
JOIN Products p ON p.product_id = t.object_id AND t.object_type = 'products'
AND
SELECT *
FROM Translations t
JOIN Categories c ON c.category_id = t.object_id AND t.object_type = 'categories'
Also after delete row in products or categories to cascade delete it from translations;
I need to list the two ENTITY_ID's (by querying the RELATIONS table with WHERE between two dates) related to each SOURCE/ACCOUNT pairs in the RELATIONS table.
- ENTITIES table
ENTITY_ID (PK)
ENTITY_NAME
- ACCOUNTS table
SOURCE (PK)
ACCOUNT (PK)
ENTITY_ID (FK)
- RELATIONS table
RELATION_ID (PK)
SOURCE_1 (FK)
ACCOUNT_1 (FK)
SOURCE_2 (FK)
ACCOUNT_2 (FK)
TIMESTAMP
The query below retrieves the ENTITY_ID of one SOURCE/ACCOUNT pair (SOURCE_1/ACCOUNT_1), but I'd also need the ENTITY_ID of SOURCE_2/ACCOUNT_2, not as second column in the output, but as a second row (value).
SELECT A.ENTITY_ID
FROM RELATIONS R
JOIN ACCOUNTS A
ON R.SOURCE_1 = A.SOURCE
AND R.ACCOUNT_1 = A.ACCOUNT
WHERE R.TIMESTAMP >= DATETIME1 AND R.TIMESTAMP < DATETIME2
Example of output needed (1 column, 2 values):
ENTITY_ID
Output record #1 1234
Output record #2 1235
If you need the values in different rows, then you can do:
SELECT A.ENTITY_ID
FROM RELATIONS R JOIN
ACCOUNTS A
ON (R.SOURCE_1 = A.SOURCE AND
R.ACCOUNT_1 = A.ACCOUNT
) OR
(R.SOURCE_2 = A.SOURCE AND
R.ACCOUNT_2 = A.ACCOUNT
)
WHERE R.TIMESTAMP >= DATETIME1 AND
R.TIMESTAMP < DATETIME2;
ORs generally kill the performance of JOINs, but this will work if your data is not very big.
I need to query the RELATIONS table (WHERE between two dates) and get the ENTITY_ID related of each SOURCE/ACCOUNT pairs in the RELATIONS table.
- ENTITIES table
ENTITY_ID (PK)
ENTITY_NAME
- ACCOUNTS table
SOURCE (PK)
ACCOUNT (PK)
ENTITY_ID (FK)
- RELATIONS table
RELATION_ID (PK)
SOURCE_1 (FK)
ACCOUNT_1 (FK)
SOURCE_2 (FK)
ACCOUNT_2 (FK)
TIMESTAMP
Is there a way to do this in one query?
Output of query should look like this:
RELATION_ID
SOURCE_1
ACCOUNT_1
ENTITY_ID_1 (ENTITY_ID (from ACCOUNTS table) related to SOURCE_1 and ACCOUNT_1)
SOURCE_2
ACCOUNT_2
ENTITY_ID_2 (ENTITY_ID (from ACCOUNTS table) related to SOURCE_2 and ACCOUNT_2)
I have an idea on how to get ENTITY_ID_1, but not sure how to get ENTITY_ID_2 at the same time.
SELECT
R.RELATION_ID
,R.SOURCE_1
,R.ACCOUNT_1
,A.ENTITY_ID AS ENTITY_ID_1
,R.SOURCE_2
,R.ACCOUNT_2
FROM RELATIONS R
JOIN ACCOUNTS A
ON R.SOURCE_1 = A.SOURCE
AND R.ACCOUNT_1 = A.ACCOUNT
WHERE R.TIMESTAMP >= DATETIME1 AND R.TIMESTAMP < DATETIME2
Any thoughts on a better title for this question is welcomed.
I think you just need two JOINs:
SELECT R.RELATION_ID, R.SOURCE_1, R.ACCOUNT_1,
A1.ENTITY_ID AS ENTITY_ID_1,
A2.ENTITY_ID AS ENTITY_ID_2,
R.SOURCE_2, R.ACCOUNT_2
FROM RELATIONS R JOIN
ACCOUNTS A1
ON R.SOURCE_1 = A1.SOURCE AND
R.ACCOUNT_1 = A1.ACCOUNT JOIN
ACCOUNT A2
ON R.SOURCE_2 = A2.SOURCE AND
R.ACCOUNT_2 = A2.ACCOUNT
WHERE R.TIMESTAMP >= DATETIME1 AND
R.TIMESTAMP < DATETIME2
Structure of the Category table:
id
title
parent_id
Structure of the Item table:
id
title
is_active (0 или 1)
category_id
table structure
Tables are associated with the category_id field by a one-to-many relationship. Those. 1 category can have many items.
The two-level hierarchy in the Category table. This defines the main categories and subcategories. Categories are those records in which parent_id = NULL. And subcategories, these are those records in which parent_id = to some id.
One Item can belong to both the main category (where parent_id = null) and the subcategory (child). Item can be active and not active (0 or 1).
You need to make a query and select from the Category table all the main categories (which have parent_id = null) that have active items (is_active = 1) and which have subcategories also with active itemes.
i.e If the child subcategory has items with is_active = 0, then do not display this category.
I could only choose the main categories in which only active items:
SELECT categories.title, count(analyses.id) FROM items
INNER JOIN categories on items.category_id = categories.id
WHERE categories.parent_id IS NULL
AND categories.is_active = 1
GROUP BY analyses.category_id
ORDER BY analyses_categories.title
But with subcategories can not cope anymore, tell me please who has more experience.
It's a little unclear what you are trying to count (just the active items associated with the parent?), but I would use exists to find out which have children with active items as well:
select c.title, count(*)
from categories c
join item i on i.category_id = c.id
where c.parent_id is null and i.is_active = 1 and exists (
select 1
from categories c2
join item i on c2.id = i.category_id
where c2.parent_id = c.id and i.is_active = 1
)
group by c.title
Tables:
users: id INT
items: id INT
setid INT
sets: id INT
relationships: userid INT
itemid INT
relationship ENUM('owner', 'participant')
Given a userid and a setid, we need to generate a list of all the items in the set, and the user’s relationship to each item, if a relationship exists. i.e. the results would
setid itemid relationship
---------------------------------
1 1 NULL
1 2 owner
....
The following doesn't work, because the second where clause eliminates rows where relationship is null:
select
sets.id as setid,
items.id as itemid,
relatonships.relationship as relationship
from sets
inner join items on sets.id = items.setid
left join relationships on relationships.itemid = items.id
where
sets.id = 5
and relationships.userid = 27
However, the second where clause eliminates rows where there is no existing relationship between that item and the given user. How can this be done with a single query?
It was very simple, I didn't understand you could test against a constant in a 'join ... on' clause:
select
sets.setid,
items.itemid,
relationships.relationship
from sets
inner join items on items.setid = sets.id
left join relationships
on relationships.itemid = items.id
and relationships.userid = 5
where
sets.id = 1
Not 100% what you are asking, by try this
select
sets.id as setid,
items.id as itemid,
relatonships.relationship as relationship
from sets
inner join items on sets.id = items.event
LEFT join relationships on relationships.itemid = items.id
where
sets.id = [say, 5]
and relationships.userid = [say, 27]
Keep in mind that the relationship column will be NULL if none exists. Also, the relationship reference in the WHERE clause could eliminate rows as well. Hope this gets you start, again I might misunderstand what you are trying to achieve. From your table design, there does not seem to be a relationship between the user and the sets, could you possibly the list of fields in the tables.
Try the following query:
select sets.id as setId,
items.id as ItemId,
relationships.relationship
from sets
join users on 1=1
join items on sets.id=items.setid
left join relationships on relationships.itemId = items.id
where
sets.id=5 and users.id = 27
By adding the users table to the join with 1=1, you do not need the where clause to reference the relationship table at all
Change the left join to:
left join relationships on relationships.itemId = items.id
AND relationships.userId=users.id