TSQL Max Function not working right - join

Using TSQL -
Trying to get most recent MAX(HAR_ASSESSMENT.SESSION_DATE) but my query is returning the oldest assessment date instead of the most recent. I think it has something to do with the SERVICE_DELIVERIES join and parameter...any suggestions would be appreciated.
**SELECT
HAR_ASSESSMENTS.NEXT_SESSION_DATE
,HAR_CONSUMERS.CLIENT_ID
,HAR_CONSUMERS.FULL_NAME
,MAX (HAR_SERVICE_DELIVERIES.SERVICE_PERIOD_START) AS Max_SERVICE_PERIOD_START
,HAR_SERVICE_DELIVERIES.SERVICE
,HAR_ASSESSMENTS.ASSESSFORM_NAME
,MAX(HAR_ASSESSMENTS.SESSION_DATE) AS Max_SESSION_DATE
,HAR_SERVICE_DELIVERIES.AGENCY
,HAR_SERVICE_DELIVERIES.PROVIDER
,HAR_SERVICE_DELIVERIES.FUND_IDENTIFIER
FROM
HAR_CONSUMERS
INNER JOIN HAR_ASSESSMENTS
ON HAR_CONSUMERS.CONSUMER_UUID = HAR_ASSESSMENTS.CONSUMER_UUID
INNER JOIN HAR_SERVICE_DELIVERIES
ON HAR_CONSUMERS.CONSUMER_UUID = HAR_SERVICE_DELIVERIES.CONSUMER_UUID
WHERE
HAR_SERVICE_DELIVERIES.SERVICE_PERIOD_START >= #SERVICE_PERIOD_START
AND HAR_SERVICE_DELIVERIES.SERVICE_PERIOD_START <= #SERVICE_PERIOD_START2
AND HAR_SERVICE_DELIVERIES.SERVICE IN (#SERVICE)
AND HAR_ASSESSMENTS.ASSESSFORM_NAME IN (#ASSESSFORM_NAME)
AND HAR_ASSESSMENTS.AGENCY IN (#AGENCY)
GROUP BY
HAR_ASSESSMENTS.NEXT_SESSION_DATE
,HAR_CONSUMERS.CLIENT_ID
,HAR_CONSUMERS.FULL_NAME
,HAR_SERVICE_DELIVERIES.SERVICE
,HAR_ASSESSMENTS.ASSESSFORM_NAME
,HAR_SERVICE_DELIVERIES.AGENCY
,HAR_SERVICE_DELIVERIES.PROVIDER
,HAR_SERVICE_DELIVERIES.FUND_IDENTIFIER**

Related

SQL is incomplete while searching with ransack

I have the following relationship in Rails: Campaign -has-many- Promise(s)
And I have the following Ruby code to return verbose list of campaigns with promises count:
def campaigns
results = Campaign
.where(user_id: current_user.id)
.left_outer_joins(:promises)
.select('campaigns.*', 'COUNT(DISTINCT promises.id) AS promises_count')
.group('campaigns.id')
.ransack(params[:q])
.result(distinct: true)
render json: {
results: results.page(params[:page]).per(params[:per_page]),
total_results: results.count(:id)
}
end
Everything works fine, unless I try to sort by promises_count. Ransack (or something else?) generates the following SQL for Postgres:
SELECT DISTINCT
campaigns.*,
COUNT(DISTINCT promises.id) AS promises_count
FROM "campaigns"
LEFT OUTER JOIN "promises"
ON "promises"."campaign_id" = "campaigns"."id"
LEFT OUTER JOIN "promises" "promises_campaigns"
ON "promises_campaigns"."campaign_id" = "campaigns"."id"
WHERE "campaigns"."user_id" = 1 GROUP BY campaigns.id;
It works, but there is no ORDER BY for some reason. When I sort by other properties, it works fine. I think Ransack is missing something, and handles promises_count different way because it's generated property and not real one.
It's possible to sort in Postgres, for example, manual query with added ORDER BY works:
SELECT DISTINCT
campaigns.*,
COUNT(DISTINCT promises.id) AS promises_count
FROM "campaigns"
LEFT OUTER JOIN "promises"
ON "promises"."campaign_id" = "campaigns"."id"
LEFT OUTER JOIN "promises" "promises_campaigns"
ON "promises_campaigns"."campaign_id" = "campaigns"."id"
WHERE "campaigns"."user_id" = 1
GROUP BY campaigns.id
ORDER BY promises_count desc;
How do I make Ransack work? I tried different combinations of queries without too much luck.

Where Clause with Less/Greater than after a Join

I'm trying to combine a joins with a where clause but the where clause is not testing an equality, it is testing for greater than or equal.
I know in a standard where clause, I can just do this:
Group.where("vote_deadline_at <= ?", Time.now)
to find all groups whose vote deadline is in the future.
However, what if this comes after a joins, like this:
User.likes.where(liked_type: "Post").joins("INNER JOIN posts ON posts.id = liked_id").where(posts: {context_type:"Group"}).joins("INNER JOIN groups ON groups.id = posts.context_id").where(groups: {"vote_deadline_at <= ?",Time.now})
Everything up to the final where(groups: {"vote_deadline_at <= ?",Time.now}) clause works fine. It returns an ActiveRecord collection of 186 rows. However, when I add the final where clause, I get the error:
SyntaxError: unexpected '}', expecting end-of-input
...ote_deadline_at <= ?",Time.now})
Is there any way to further filter my results with a where clause that selects only rows where groups.vote_deadline_at is in the future (i.e. less than or equal to Time.now)?
I thought I had tried this before, but apparently this syntax works:
u.likes.where(liked_type: "Post").joins("INNER JOIN posts ON posts.id = liked_id").where(posts: {context_type:"Group"}).joins("INNER JOIN groups ON groups.id = posts.context_id").where("groups.vote_deadline_at <= ?",Time.now)
I got exactly the results I expected.
The syntax should be:
... .where(groups: ["vote_deadline_at <= ?",Time.now] )

Using distinct in a join

I'm still a novice at SQL and I need to run a report which JOINs 3 tables. The third table has duplicates of fields I need. So I tried to join with a distinct option but hat didn't work. Can anyone suggest the right code I could use?
My Code looks like this:
SELECT
C.CUSTOMER_CODE
, MS.SALESMAN_NAME
, SUM(C.REVENUE_AMT)
FROM C_REVENUE_ANALYSIS C
JOIN M_CUSTOMER MC ON C.CUSTOMER_CODE = MC.CUSTOMER_CODE
/* This following JOIN is the issue. */
JOIN M_SALESMAN MS ON MC.SALESMAN_CODE = (SELECT SALESMAN_CODE FROM M_SALESMAN WHERE COMP_CODE = '00')
WHERE REVENUE_DATE >= :from_date
AND REVENUE_DATE <= :to_date
GROUP BY C.CUSTOMER_CODE, MS.SALESMAN_NAME
I also tried a different variation to get a DISTINCT.
/* I also tried this variation to get a distinct */
JOIN M_SALESMAN MS ON MC.SALESMAN_CODE =
(SELECT distinct(SALESMAN_CODE) FROM M_SALESMAN)
Please can anyone help? I would truly appreciate it.
Thanks in advance.
select distinct
c.customer_code,
ms.salesman_code,
SUM(c.revenue_amt)
FROM
c_revenue c,
m_customer mc,
m_salesman ms
where
c.customer_code = mc.customer_code
AND mc.salesman_code = ms.salesman_code
AND ms.comp_code = '00'
AND Revenue_Date BETWEEN (from_date AND to_date)
group by
c.customer_code, ms.salesman_name
The above will return you any distinct combination of Customer Code, Salesman Code and SUM of Revenue Amount where the c.CustomerCode matches an mc.customer_code AND that same mc record matches an ms.salesman_code AND that ms record has a comp_code of '00' AND the Revenue_Date is between the from and to variables. Then, the whole result will be grouped by customer code and salesman name; the only thing that will cause duplicates to appear is if the SUM(revenue) is somehow different.
To explain, if you're just doing a straight JOIN, you don't need the JOIN keywords. I find it tends to convolute things; you only need them if you're doing an "odd" join, like an LEFT/RIGHT join. I don't know your data model so the above MIGHT still return duplicates but, if so, let me know.

Bulk updating a joined table with ActiveRecord update_all and Rails 4

I have a PostgreSQL query that I would like to write in ActiveRecord (Rails 4), but I'm having trouble getting it to work correctly.
UPDATE chats AS c
SET email = m.source_name
FROM messages AS m
WHERE c.id = m.chat_id
AND m.created_at >= '2014-10-10'
This is what I've tried:
Chat.joins(:messages)
.where("message.created_at >= '2014-10-10'")
.update_all('chat.email = message.source_name')
But it creates a query like this:
UPDATE "chats"
SET chat.email = message.source_name
WHERE "chats"."id" IN (
SELECT "chats"."id"
FROM "chats"
INNER JOIN "messages"
ON "messages"."chat_id" = "chats"."id"
WHERE (message.created_at >= '2014-10-10')
)
Any help on this?
Since Chat.update_all will add UPDATE chats SET... the only way that I can think of get rails to do an update with an alias (UPDATE chats AS c) is by using connection.update and a sql string:
Chat.connection.update(Q%{
UPDATE chats AS c
SET email = m.source_name
FROM messages AS m
WHERE c.id = m.chat_id
AND m.created_at >= '2014-10-10'
});
Not great if you want to avoid SQL fragments, but using an a join as in your question may be the only way if you want to use AREL.

How to convert SQL query to ActiveRecord

Background:
Writing a Ruby on Rails app that is connect to MS SQL DB(don't ask why, its something I cant get around), the DB is quiet large and can have up to 2/3 million rows.
There is one main columns that matter for me at the moment and that is 'TimeUTC' and the table is called ApplicationLog and the query will be in the ApplicationLogController.
Problem:
I want to write a query that i can pass in two dates and it will group all the records by day using the 'TimeUTC' column and gives me a total of all the records for those days in between those two dates.
I have the SQL Query:
DECLARE #StartDate DateTime = '2014-01-04 00:00:00'
DECLARE #EndDate DateTime = '2014-02-04 23:59:59'
select (dateadd(DAY,0, datediff(day,0, TimeUtc))) as [DATE], count(*)
from applicationlog (nolock)
where TimeUtc between #StartDate and #EndDate
group by dateadd(DAY,0, datediff(day,0, TimeUtc))
order by [DATE] desc
I try starting with something like this:
#results = ApplicationLog.select((dateadd(DAY,0, datediff(day,0, TimeUtc)) as [date], count(*)).
group(dateadd(DAY,0, datediff(day,0, TimeUtc))).order(date desc)
Now I am a newbie at this so I could be so far off the track its not funny, but any help would be great. Am I even going about this the right way, is there a better way??
Try with the following code, which uses Arel code with some SQL embedded.
class ApplicationLog < ActiveRecord::Base
def self.between(range)
columns = Arel.sql('dateadd(DAY,0,datediff(day,0,TimeUtc)) as date, COUNT(*)')
conditions = arel_table['TimeUTC'].in(range)
query = arel_table.project(columns).where(conditions).group([1]).order('date desc')
ActiveRecord::Base.connection.execute(query.to_sql)
end
end
Then use ApplicationLog.between(1.week.ago..Time.now).

Resources