How to do left join twice in one query? - sql

How to do left join twice or other way to get data in result list like below in one query ?
I want media_information under media
{
id: 9,
gallery_id: 25,
media_id: 9,
media: {
id: 9,
media_information: {
id: 9,
media_id: 9,
}
},
}
query I tried
var dbQuery = `SELECT
gm.*,
row_to_json(m.*) as media,
row_to_json(mi.*) as media_information
FROM "gallery_media" gm
LEFT JOIN media m ON gm.media_id = m.id
LEFT JOIN media_information mi ON gm.media_id = mi.media_id
WHERE "gallery_id" = $1
ORDER BY gm.create_date DESC OFFSET $2 LIMIT $3`;
result
{
id: 9,
gallery_id: 25,
media_id: 9,
media: {
id: 9,
},
media_information: {
id: 9,
media_id: 9,
}
}
UPDATE
I also tried change ON m.id = mi.media_id but result nothing change
var dbQuery = `SELECT
gm.*,
row_to_json(m.*) as media,
row_to_json(mi.*) as media_information
FROM "gallery_media" gm
LEFT JOIN media m ON gm.media_id = m.id
LEFT JOIN media_information mi ON m.id = mi.media_id
WHERE "gallery_id" = $1
ORDER BY gm.create_date DESC OFFSET $2 LIMIT $3`;
table
CREATE TABLE IF NOT EXISTS "gallery_media"(
"id" SERIAL NOT NULL,
"gallery_id" integer NOT NULL,
"media_id" integer NOT NULL,
PRIMARY KEY ("id")
);
CREATE TABLE IF NOT EXISTS "media"(
"id" SERIAL NOT NULL,
PRIMARY KEY ("id")
);
CREATE TABLE IF NOT EXISTS "media_information"(
"id" SERIAL NOT NULL,
"media_id" integer NOT NULL,
PRIMARY KEY ("id") );
http://sqlfiddle.com/#!15/ff805

I think this is what you're after:
var dbQuery = `SELECT
gm.*,
row_to_json(m.*) as media,
row_to_json(mi.*) as media_information
FROM "gallery_media" gm
LEFT JOIN media m ON gm.media_id = m.id
LEFT JOIN media_information mi ON m.id = mi.media_id
WHERE "gallery_id" = $1
ORDER BY gm.create_date DESC OFFSET $2 LIMIT $3`;
ie: doing your second LEFT JOIN on media instead of gallery_media

Related

Make SELECT subquery COUNT the total subscribers of a subscriber

I trying to create a query that counts the total subscribers of a subscriber. It currently looks like this:
await this.queryInstance.query(
'SELECT all_users_subbed_to.* , (SELECT COUNT(??????)) AS subscribers_sub_count
FROM
(SELECT publisher_id, subscriber_id, u2.username
AS username, u2.user_photo AS user_photo
FROM subscribers s
INNER JOIN users u
ON (u.id = s.subscriber_id)
INNER JOIN users u2 ON (u2.id = s.publisher_id)
WHERE subscriber_id = ($1)
LIMIT 20
OFFSET ($2))
AS all_users_subbed_to;'
,
[currentUserId = 80, offset]
);
The FROM CLAUSE AKA all_users_subbed_to is WORKING correctly and displays a ALL the subscribers the current user has. The data comes back as this:
"subscribedToCurrentUser": [
{
"publisher_id": 84,
"subscriber_id": 80,
"username": "supercoookie",
"user_photo": "profile-pic-for-supercoookie.jpeg"
},
{
"publisher_id": 88,
"subscriber_id": 80,
"username": "GERPAL1",
"user_photo": "profile-pic-for-GERPAL1.jpeg"
}
]
The issue I am having is getting the total subscriber counts for the list of those subscribers. I need to use the subscribers publisher_id ie all_users_subbed_to.publisher_id and get their total subs (using COUNT) from the subscribers table. I would like to create a new column called have subscribers_sub_count that contains that total.
Any ideas?
It should look like this:
"subscribedToCurrentUser": [
{
"publisher_id": 84,
"subscriber_id": 80,
"username": "supercoookie",
"user_photo": "profile-pic-for-supercoookie.jpeg",
"subscribers_sub_count": 3
},
{
"publisher_id": 88,
"subscriber_id": 80,
"username": "GERPAL1",
"user_photo": "profile-pic-for-GERPAL1.jpeg",
"subscribers_sub_count": 70
}
]
The subscribers table looks like this:
await this.queryInstance.query(
'SELECT all_users_subbed_to.*, COUNT(all_users_subbed_to.id) AS subscribers_sub_count
FROM
(SELECT publisher_id, subscriber_id, u2.username
AS username, u2.user_photo AS user_photo
FROM subscribers s
INNER JOIN users u
ON (u.id = s.subscriber_id)
INNER JOIN users u2 ON (u2.id = s.publisher_id)
WHERE subscriber_id = ($1)
LIMIT 20
OFFSET ($2))
AS all_users_subbed_to;'
,
[currentUserId = 80, offset]
);
Fixed it. It just needed a WHERE clause that used data from all_users_subbed_to
await this.queryInstance.query(
'SELECT all_users_subbed_to.* ,
(SELECT COUNT(*) FROM subscribers s2 WHERE s2.publisher_id = all_users_subbed_to.publisher_id) AS subscribers_sub_count AS subscribers_sub_count
FROM
(SELECT publisher_id, subscriber_id, u2.username
AS username, u2.user_photo AS user_photo
FROM subscribers s
INNER JOIN users u
ON (u.id = s.subscriber_id)
INNER JOIN users u2 ON (u2.id = s.publisher_id)
WHERE subscriber_id = ($1)
LIMIT 20
OFFSET ($2))
AS all_users_subbed_to;'
,
[currentUserId = 80, offset]
);

Writing sequelize queries for geometries in POSTGRES

I have the following query and want to write it as a sequelize query
`SELECT "Gigs"."id",
"gigType",
"gigCategory",
"gigTitle",
"gigDescription",
"minOrderAmount",
unit,
"unitPrice",
stock,
sold,
"expireDate",
"Gigs".userid AS "sellerId",
"growerType" AS "sellerType",
"points",
json_build_object('id', "locationId", 'lat', lat, 'lng', lng) AS location
FROM (SELECT DISTINCT ON ("gigid") "gigid", "locationId", lat, lng
FROM (SELECT "gigid",
id as "locationId",
st_x(coordinates::geometry) as lat,
st_y(coordinates::geometry) as lng
FROM "Locations"
WHERE ST_DWithin(coordinates,
ST_MakePoint(${location.lat}, ${location.lng})::geography,
${distance})
ORDER BY coordinates <-> ST_MakePoint(${location.lat}, ${location.lng})::geography
LIMIT ${limit}) AS nearGigIds) AS distinctGigIds
INNER JOIN "Gigs"
ON distinctGigIds."gigid" = "Gigs"."id"
INNER JOIN "Users" U
ON U.id = "Gigs".userid
INNER JOIN "Customers" C on U.id = C.userid
INNER JOIN "Growers" G on C.userid = G.userid
WHERE "expireDate" > ${today}::text::date
ORDER BY points DESC
OFFSET ${offset} LIMIT 10;`
I want to know how to write ORDER BY coordinates <-> ST_MakePoint(${location.lat}, ${location.lng})::geography part in the query. I referred the docs and there is a way to write functions in ORDER BY as follows.
order: [
// Will order by otherfunction(`col1`, 12, 'lalala') DESC
[sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
],
});
But I am confused about how to write the aforesaid part like this.
db.Table.findAll({
attributes: {
include: [
[
Sequelize.fn(
'ST_Distance',
Sequelize.fn('point', Sequelize.col('longitude'), Sequelize.col('latitude')),
Sequelize.fn('point', longitude, latitude),
),
'distanceAttribute',
],
],
},
order:[['distanceAttribute', 'DESC']]
});

PSQL Join alternative to return all rows

I've got a PSQL function that has 3 joins in it and the data is returned in a json object. I have a 4th table that I need to get data from but it has a one-to-many relationship with the table I wish to join on.
This is my current code:
select json_agg(row_to_json(s)) as results from (
select g.*,row_to_json(o.*) as e_occurence,
row_to_json(d.*) as e_definition,
row_to_json(u.*) as e_e_updates,
cardinality(o.m_ids) as m_count
from schema.e_group g
join schema.e_occurrence o on g.id = o.e_group_id
join schema.e_definition d on g.e_id = d.id
left join schema.e_e_updates u on d.id = u.e_id
) s
This gets me an array of objects that follows this rough structure:
[
{
"id": 11308158,
"e_id": 16,
"created_on": "2020-09-09T12:08:07.556062",
"event_occurence": {
"id": 9081887,
"e_id": 16,
"e_group_id": 11308158
},
"e_definition": {
"id": 16,
"name": "Placeholder name"
},
"e_e_updates": {
"id": 22,
"user_id": "7281057e-2876-1673-js7d-7cqj611b4557",
"e_id": 16
},
"m_count": 0
}
]
My problem is that the table e_e_updates can have multiple records for each corresponding e_definition.id.
Clearly the join will not work as hoped in this instance as I'd like e_e_updates to be an array of all the linked rows.
Is there an alternative means of solving this issue?
Basically, you need another level of aggregation. This should do what you want:
select json_agg(row_to_json(s)) as results
from (
select
g.*,
row_to_json(o.*) as e_occurence,
row_to_json(d.*) as e_definition,
u.u_arr as e_e_updates,
cardinality(o.m_ids) as m_count
from schema.e_group g
join schema.e_occurrence o on g.id = o.e_group_id
join schema.e_definition d on g.e_id = d.id
left join (
select e_id, json_agg(row_to_json(*)) u_arr
from schema.e_e_updates
group by on e_id
) u on d.id = u.e_id
) s
You could also do this with a subquery:
select json_agg(row_to_json(s)) as results
from (
select
g.*,
row_to_json(o.*) as e_occurence,
row_to_json(d.*) as e_definition,
(
select json_agg(row_to_json(u.*))
from schema.e_e_updates u
where u.e_id = d.id
) as e_e_updates,
cardinality(o.m_ids) as m_count
from schema.e_group g
join schema.e_occurrence o on g.id = o.e_group_id
join schema.e_definition d on g.e_id = d.id
) s

Two queries return different data

I am running two queries according to me both should return same result, but i think i am missing something
SELECT "id", "email", "first_name", "last_name", locale
FROM "users" AS "users"
WHERE (
EXISTS (
SELECT cf.field_value, ucf.field_value
FROM custom_fields cf
LEFT JOIN users_custom_fields ucf ON cf."id" = ucf.custom_field_id
WHERE cf."id" = 272 AND
((
cf.field_value = 'true') OR
(
ucf.user_id = users.id AND ucf.field_value = 'true'))
))
it returns record
SELECT users.id, cf.field_value, ucf.field_value, ucf.user_id
FROM users
Join custom_fields cf on cf.user_id = users.id
LEFT join users_custom_fields ucf on ucf.custom_field_id = cf."id"
WHERE cf."id" = 272 AND
((
cf.field_value = 'true') OR
(ucf.user_id = users.id AND ucf.field_value = 'true'))
and it doesn't return anything, is there any difference between these two?
your second query you also join custom_fields table with cf.user_id = users.id. first query does not have this.
With adding cf.user_id = users.id, your first query equal the second.
SELECT "id", "email", "first_name", "last_name", locale FROM "users" AS "users" WHERE (
EXISTS (
SELECT cf.field_value, ucf.field_value
FROM custom_fields cf
LEFT JOIN users_custom_fields ucf ON cf."id" = ucf.custom_field_id
WHERE cf."id" = 272
AND cf.user_id = users.id
AND (( cf.field_value = 'true') OR
( ucf.user_id = users.id AND ucf.field_value = 'true'))
))

Convert SQL query with inner, left, and nested select to LINQ

how can convert this query to linq?
SELECT p.PostID, p.PostText, p.PublishDate, u.Name
FROM AspNetUsers u INNER JOIN Posts p ON u.Id = p.PostUserID LEFT JOIN Reposts r ON p.PostID = r.PostID
WHERE p.PostUserID = 'id'
OR p.PostUserID IN ( SELECT FollowingUserID FROM Friends WHERE FollowerUserID = 'id' AND isUnfollow = 0)
OR p.PostID in (SELECT PostID FROM Reposts WHERE RepostUserID = 'id' OR RepostUserID IN ( SELECT FollowingUserID FROM Friends WHERE FollowerUserID = 'id' AND isUnfollow = 0))
ORDER BY p.PostUserID
Does this work?
var results = from u in AspNetUsers
join p in Posts on u.Id equals p.PostUserID
join r in Reposts on p.PostId equals r.PostId into records
from record in records.DefaultIfEmpty()
where p.PostUserID == "id"
|| (from friend in Friends
where friend.FollowerUserID == "id"
&& friend.isUnfollow == 0
select friend.FollowingUserID
).Contains(p.PostUserID)
|| (from r2 in Reposts
where r2.RepostUserID == "id"
|| (from friend2 in Friends
where friend2.FollowerUserID == "id"
&& friend2.isUnfollow == 0
select friend2.FollowingUserID
).Contains(r2.RepostUserID)
select r2.PostID
).Contains(p.PostID)
orderby p.PostUserID ascending
select p.PostID, p.PostText, p.PublishDate, u.Name;