Does row-level security (RLS) apply on a join statement? - sql

Given the following (simplified) tables:
users
-----
id (pk)
posts
-----
id (pk)
user_id (fk)
likes
-----
user_id (pk)
post_id (pk)
If I run the following query to get which posts a user (?) liked:
SELECT *
FROM posts p
INNER JOIN likes l
ON l.post_id = p.id
WHERE l.user_id = ?
Would the RLS policy for SELECT on the likes table and posts table both be invoked, or would it only apply to the posts table since that is where we are SELECTing FROM? I'm under the assumptiom that it would apply for both tables, but just wanted to double check and make sure. I'm using PostgreSQL if that makes any difference.
Thanks for any help!

If a user doesn't have permission to see rows in a table, that applies to the entire query, not just to the columns being returned.
Basically, the table (or rows) will be invisible to the user.

Related

two foreign keys on same table to display parent fields

i have two tables
details like below
user master
----------------
userid int (pk)
username
useraddress
user transactions
-----------------
fromUser int (fk - userid)
toUser int (fk - userid)
amount
i need to display data as follows
fromUsername
toUsername
amount
i tried many queries but i am unable to form a proper select query
tried googling and much more but due to lack of searching with proper keyword i am unable to find the desired answer
You just need two joins:
select mf.username, mt.username, t.amount
from transactions t join
master mf
on t.fromUser = mf.userId join
master mt
on t.toUser = mt.userId;
If either user could be NULL or invalid, use left join instead of join.

Join Three Tables and Use Count on One of Them

I'm trying to improve my querying abilities and I have been having trouble wrapping my head around joins of moderate complexity. To be as clear and concise as possible, I am trying to join 3 tables. The first join selects posts from all users on users.User_ID=posts.FK_User_ID
**User table**
User_ID pk
username int
email
etc...
**Post Table**
post_ID PK
User_ID FK
Post
etc...
**Like Table**
FK_User_ID references user.user_ID
FK_Post_ID references post.Post_ID (*This is what I want to count*)
after this I want to reference a third table. This table contains a Foreign key to user_ID of user table and a foreign key of FK_Post_ID referencing the primary key Post_ID in the post table. This third table is a linking table of users who have liked the post. I want to count all occurrences of a post ID in this table and append it to each post in the initial user and post join so an output result would look like this:
User_id Username Post_ID Post Number_of_Likes
1 bob 4 'foo' 18
my first join between the two tables works and looks like this (simplified with * for example)
select * from users
join post
on post.User_ID=users.User_ID
Now I need a way to reference the third table to count the total # of times that a post id appears in the like table and append it to each row. This is where I am lost, I have been trying a lot of things to no luck. I believe I need to construct an inner join clause for my second join or I need to pull off a nested select statement? Could someone correct me on this if I am wrong and perhaps guide me in the right direct? Appreciate it!
A common way to do this is make a sub-query that has counts and key then join to that. Like this:
select *
from users
join post on post.FK_User_ID=users.User_ID
left join (
select FK_Post_ID, count(*) as count_of_likes_on_a_post
from likestable
group by FK_Post_ID
) likes on post.Post_ID = likes.FK_Post_ID

How do I establish a SQL query for this many-to-many table?

I'm building this bartering-type function in this site using PHP/MySQL and I'm trying to create a query that responds with the following fields:
owner's username, title, offerer's username, offerer's item
Basically I have three tables here with the following fields:
users
user_id, username, email
items_available
item_number, owner_id (foreign key that links to user_id), title
offers_open
trade_id, offerers_id (fk of user_id), offerers_item(fk with item_number), receivers_id (fk from user_id)
How do I do this? I've seen some references to many-to-many SQL queries but they don't seem to particularly fit what I'm looking for (for example, the offerers_id and the owner_ids refer to different users_id in the Users table, but how do I make them distinguishable in the sql query?)
If I understand correctly, this is what you are looking for:
SELECT owner.username, oferrers.username, ia.title
FROM offers_open o
INNER JOIN users AS offerers
ON o.offerers_id = offerers.user_id
INNER JOIN items_available AS ia
ON o.offerers_item= ia.item_number
INNER JOIN users AS owner
ON ia.owner_id = owner.user_id
I don't see a title on the users table, so didn't include one.
I'm not sure exactly what output you want, but since your users table will appear twice in the query, they need to be aliased like so:
SELECT offerer.username AS offerer_username, title, receiver.username AS receiver_username
FROM users AS owner
JOIN items_available ON owner_id = owner.user_id
JOIN offers_open ON offerers_item = item_number
JOIN users AS receiver ON receivers_id
Again, don't know if that's what you want, but hope you get the idea.
It sounds as you need an alias of the users table.
Something like?
select
u.*, ia.*, oo.*,u2.*
from
users as u,
items_available as ia,
offers_open as oo,
users as u2
where
u.user_id = ia_user_id and
oo.user_id = u2.user_id and
oo.item_id = ia.item_id

SQL join on one-to-many relation where none of the many match a given value

Say I have two tables
User
-----
id
first_name
last_name
User_Prefs
-----
user_id
pref
Sample data in User_Prefs might be
user_id | pref
2 | SMS_NOTIFICATION
2 | EMAIL_OPT_OUT
2 | PINK_BACKGROUND_ON_FRIDAYS
And some users might have no corresponding rows in User_Prefs.
I need to query for the first name and last name of any user who does NOT have EMAIL_OPT_OUT as one of their (possibly many, possibly none) User_Pref rows.
SELECT DISTINCT u.* from User u
LEFT JOIN User_Prefs up ON (u.id=up.user_id)
WHERE up.pref<>'EMAIL_OPT_OUT'
gets me everyone who has at least one row that isn't "EMAIL_OPT_OUT", which of course is not what I want. I want everyone with no rows that match "EMAIL_OPT_OUT".
Is there a way to have the join type and the join conditions filter out the rows I want to leave out here? Or do I need a sub-query?
I personally think a "where not exists" type of clause might be easier to read, but here's a query with a join that does the same thing.
select distinct u.* from User u
left join User_Prefs up ON u.id = up.user_id and up.pref = 'EMAIL_OPT_OUT'
where up.user_id is null
Why not have your user preferences stored in the user table as boolean fields? This would simplify your queries significantly.
SELECT * FROM User WHERE EMAIL_OPT_OUT = false

How to write a SQL statement which gets results via a relationship table? (many to many)

I have 3 tables (archive has many sections, section (may) belong to many archives):
archive
id PK
description
archive_to_section
archive_id PK FK
section_id PK FK
section
id PK
description
What would the SQL look like to list all the sections that belong a certain archive id?
I am just learning SQL. From what I've read it sounds like I would need a join, or union? FYI I'm using postgres.
[Edit] This is the answer from gdean2323 written without aliases:
SELECT section.*
FROM section
INNER JOIN archive_to_section
ON section.id = archive_to_section.section_id
WHERE archive_to_section.archive_id = $this_archive_id
SELECT s.*
FROM section s INNER JOIN archive_to_section ats ON s.id = ats.section_id
WHERE ats.archive_id = 1
SELECT s.*
FROM archive_to_section ats
INNER JOIN section s ON s.id=ats.section_id
WHERE ats.archive_id= #archiveID