Using limit in array_agg in Postgres - sql

I am fetching user's tasks as an array using array_agg function in postgres but I want to limit it to latest 10 tasks. I am unable to use LIMIT in subquery. I also tried to use row_number function but it throws error that window functions can not be used in WHERE.
Below is the query I am using.
SELECT
*,
COUNT(*) OVER () as count
FROM
(
SELECT
*,
(
SELECT
ARRAY_AGG(
JSON_BUILD_OBJECT(
'id', taskhistories.id, 'task', taskhistories.task,
'taskname', tasks.name, 'project',
taskhistories.project, 'projectname',
projects.name, 'started_at', taskhistories.started_at,
'stopped_at', taskhistories.stopped_at
)
) as tasks
FROM
taskhistories
LEFT JOIN tasks ON taskhistories.task = tasks.id
LEFT JOIN projects ON taskhistories.project = projects.id
WHERE
users.id = taskhistories.user
-- LIMIT 10 this is something I want to achieve
) AS tasks
FROM
users
WHERE
isadmin IS NOT TRUE
) as users
LIMIT
10 OFFSET 0
Schema Queries

LIMIT is executed after aggregation, so that won't work anyway. Try something like this in your subquery:
SELECT JSONB_AGG(t.task) as tasks
FROM (SELECT JSONB_BUILD_OBJECT(
'id', taskhistories.id,
'task', taskhistories.task,
'taskname', tasks.name,
'project', taskhistories.project,
'projectname', projects.name,
'started_at', taskhistories.started_at,
'stopped_at', taskhistories.stopped_at
) AS task
FROM taskhistories
LEFT JOIN tasks ON taskhistories.task = tasks.id
LEFT JOIN projects ON taskhistories.project = projects.id
WHERE users.id = taskhistories.user
LIMIT 10) AS t

Related

postgres: LEFT JOIN table and field does not exist

This is my query
SELECT org.id,
org.name,
org.type,
org.company_logo,
(SELECT org_profile.logo_url FROM org_profile WHERE org_profile.org_id = org.id AND org_profile.status = 'active' ORDER BY org_profile.id DESC LIMIT 1) as logo_url,
org.short_description,
org_profile.value_prop,
count(*) OVER () AS total
FROM org
LEFT JOIN user_info ON user_info.id = org.approved_by
INNER JOIN (select distinct org_profile.org_id from org_profile) org_profile ON org_profile.org_id = org.id
WHERE
org.type = 'Fintech'
AND org.status = 'APPROVED'
AND org.draft != TRUE
ORDER BY org.id DESC
I am using LEFT JOIN query with my org_profile table. I used distinct for unique org id but the problem is org_profile.value_prop column does not work. The error is showing column org_profile.value_prop does not exist
I'm trying to solve this issue. But I don't figure out this issue.
basically, the error informs that you try to get the value_prop field from org_profile subquery, which basically doesn't exist.
It's difficult to give a working query by writting just on the paper, but I think that:
it's worth to apply the handy aliasses for each subquery
deduplication, if required, should be done in the subquery. When multiple fields used DISTINCT may be insufficient - RANK function may be required.
you make some operations to get the logo_url by a scalar subquery - it seems a bit strange, especially the same table is used in JOIN - I would suggest to move all logic related to org_profile to the subquery. Scalar expressions would throw an error in case multiple values would be found in output.
SELECT
org.id,
org.name,
org.type,
org.company_logo,
prof.logo_url,
org.short_description,
prof.value_prop,
count(*) OVER () AS total
FROM org
JOIN (
select distinct org_id, logo_url, value_prop -- other deduplication type (RANK) may be required
from org_profile
where status = 'active' -- ?
) prof ON org.id = prof.org_id
LEFT JOIN user_info usr ON usr.id = org.approved_by
WHERE
org.type = 'Fintech'
AND org.status = 'APPROVED'
AND org.draft != TRUE
ORDER BY org.id DESC

I can not convert the data to the required form

Hi hi I have a Nodejs server and I am using PostgreSQL, the bottom part of my database.
How can I select data and represent it like this (in one sql query):
{lessons: ['lesson1','lesson2'], tests: [{quest:'quest_name',options:['opt1','opt2']}]}
I wrote a request but it is far from what I need:
SELECT tests.id,
chapter,
time,
ARRAY_AGG(quests.question) AS questions,
ARRAY_AGG(options.option) AS quest_options
FROM tests
LEFT JOIN quests ON tests.id = quests.test_id
LEFT JOIN options ON quests.id = options.quest_id
WHERE tests.course_id = '${courseId}'
GROUP BY tests.id
You can use a cte to first build the question JSON data, and then aggregate the latter with the lessons:
with tests(q, o) as (
select q.question, json_agg(o.option)
from tests t join quests q on t.id = q.test_id join options o on q.id = o.quest_id
where t.course_id = '${courseId}'
group by q.question
)
select json_build_object('lesson',
(select json_agg(l.lesson_text) from lessons l where l.course_id = '${courseId}'),
'tests',
(select json_agg(json_build_object('quest', t.q, 'options', t.o)) from tests t)
)

New to SQL writing a query with nesting and joins

Here is my query I am not sure why it wont run. it doesnt seem to like the joins. It ran without the nesting but now the now the joins wont work.
select *
from (
select * ,
row_number () over (partition by t.activity_type__c order by t.ActivityDate desc) ,
x.name,
MAX(t.ActivityDate) as Last_Activity_Date,
/* all these below x or a alias? */
x.Channel__c,
x.Account_18_Digit_ID__c,
x.Advisor_Approach__c,
x.name,
x.BillingState,
x.Current_Month_WT_AUM__c,
x.WT_ETF_AUM_mil__c,
x.ETF_AUM__c,
x.WT_ETF_Market_Share__c,
x.priority_type__C,
x.phone,
/* x.ownerid,
x.ID ? */
rn
from account a
) where rn=1
join [User] u on u.id = x.OwnerId
left join Task t on t.WhatId = x.Id
where t.Activity_Type__c <> 'attempt' and
( Advisor_Approach__c like 'CAPFINANCIAL_SECURITIES%' )
There's a lot going on here, so to start out we need to format it with better indentation. This helps make it obvious we have two where clauses at the same nesting level, one of which is out of place (before the JOINs).
Looking deeper, I see a MAX() function, but it's not allowed in this context unless you also have a GROUP BY clause. We're also missing an alias for the inner query... perhaps this is where the x is supposed to come from? And the inner nested query references columns from tables in the outer query, which are not yet available. Also, you can't use a windowing function result at the same level of nesting, and I don't see what the User table is needed for. After we fix most of this, we also no longer need to nest the accounts table by itself.
This is closest I could come to fixing all these issues, but I know it's still wrong because of (at least) the MAX() function:
select *
from (
select a.name,
/* MAX(t.ActivityDate) as Last_Activity_Date, */
a.Channel__c,
a.Account_18_Digit_ID__c,
a.Advisor_Approach__c,
a.name,
a.BillingState,
a.Current_Month_WT_AUM__c,
a.WT_ETF_AUM_mil__c,
a.ETF_AUM__c,
a.WT_ETF_Market_Share__c,
a.priority_type__C,
a.phone,
/* a.ownerid, a.ID ? */
row_number () over (partition by t.activity_type__c order by t.ActivityDate desc) as rn
from account a
join [User] u on u.id = a.OwnerId
left join Task t on t.WhatId = a.Id
where t.Activity_Type__c <> 'attempt'
and ( Advisor_Approach__c like 'CAPFINANCIAL_SECURITIES%' )
) x
where rn = 1
It seems you have the query upside-down. You seem to be trying to join the lastest task per activity type to the account, but instead of selecting from account and then joining the latest tasks, you are trying to select the lastest task from the account table somehow, which cannot work of course.
Something along the lines of:
select *
from account a
join [User] u on u.id = a.ownerid
left join
(
select
task.*,
row_number() over (partition by activity_type__c order by activitydate desc) as rn
from task
where activity_type__c <> 'attempt'
) t on t.whatid = a.id and t.rn = 1
where a.advisor_approach__c like 'CAPFINANCIAL_SECURITIES%'
order by a.id, t.activity_type__c;

SQL Fetch Query execute to slow in both server on local as well as on azure

SELECT Users.Id,
Users.IsActive,
Users.Risk,
Users.Name,
Users.EmployeeID,
Users.OrganizationId,
Users.Username,
Users.IsUser,
Users.WFID,
Organizations.Name AS orgName,
(SELECT MAX(UserTestGroups.ModifiedOn)
FROM UsersInSchedules
LEFT JOIN UserTestGroups ON UsersInSchedules.Id = UserTestGroups.UserInScheduleID
WHERE Users.Id = UsersInSchedules.UserID) AS LastTest
FROM Users
LEFT JOIN Organizations ON Users.OrganizationID = Organizations.Id
WHERE Users.isUser = '0'
AND Users.IsDeleted = '0'
ORDER BY Users.Name ASC
OFFSET 15 ROWS FETCH NEXT 15 ROWS ONLY
Above query is working too slowly, taking almost 7 seconds to respond from server.
I am not understanding why that is happening - what is wrong with the query?
Here is the execution plan for query:
The nested SELECT could be the reason for low performance of your query. The nested SELECT must be processed for each result of your outer query. I think a join approach could yield better result. You could try
SELECT Users.Id,
Users.IsActive,
Users.Risk,
Users.Name,
Users.EmployeeID,
Users.OrganizationId,
Users.Username,
Users.IsUser,
Users.WFID,
Organizations.Name AS orgName,
UserTest.LastTest
FROM Users
LEFT JOIN Organizations ON Users.OrganizationID = Organizations.Id
LEFT JOIN
(
SELECT UsersInSchedules.UserID, MAX(UserTestGroups.ModifiedOn) AS LastTest
FROM UsersInSchedules
LEFT JOIN UserTestGroups ON UsersInSchedules.Id = UserTestGroups.UserInScheduleID
GROUP BY UsersInSchedules.UserID
) UserTest ON Users.Id = UserTest.UserID
WHERE Users.isUser = '0' AND Users.IsDeleted = '0'
ORDER BY Users.Name ASC
OFFSET 15 ROWS FETCH NEXT 15 ROWS ONLY

Rails: SQL SELECT Statement Not Appearing When Combined With GROUP BY

I have the following code in Ruby:
Comment.select("comments.*, COALESCE(SUM(votes.value), 0) AS rating,
user_votes.value AS user_value").
joins("LEFT JOIN votes ON votes.voteable_type = '"+type+"' AND votes.voteable_id = comments.id").
joins("LEFT JOIN votes AS user_votes ON user_votes.voteable_type = '"+type+"' AND user_votes.voteable_id = comments.id AND user_votes.user_id = #{user_id}").
where(conditions).group("comments.id").order("comments."+method).limit(limit).offset(offset)
When Rails generates this SQL query, it doesn't include the full select statement:
SELECT COUNT(*) AS count_all, comments.id AS comments_id FROM `comments`
LEFT JOIN votes ON votes.voteable_type = 'reply' AND votes.voteable_id = comments.id
LEFT JOIN votes AS user_votes ON user_votes.voteable_type = 'reply' AND
user_votes.voteable_id = comments.id AND user_votes.user_id = 1 WHERE (commentable_id =
1 AND commentable_type = 'Impression')
GROUP BY comments.id ORDER BY comments.rating DESC LIMIT 10 OFFSET 0
If I remove the group statement, however, then it properly includes the full select statement. What's going on?
select comments.* in your select statement conflicts with group by("comments.id").
Every column selected must either be in the GROUP BY clause or be contained in an aggregate function.
SQL Server shows error for SQL:
select c.* from tt_country c group by c.name
Column 'tt_country.country_id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
ActiveRecord and arel throws out the specified select because it is ambiguous / invalid.