MySQL to Postgres group_by error - mysql

The following query works fine in MySQL (which is generated by rails):
SELECT
sum(up_votes) total_up_votes
FROM
"answers"
WHERE
"answers"."user_id" = 100
ORDER BY
"answers"."id" ASC
Yet it gives the following error in Postgres:
PG::GroupingError: ERROR: column "answers.id" must appear in the GROUP BY clause or be used in an aggregate function
Edit: updated query. And here is the Rails model where this query is performed:
class User < MyModel
def top?
data = self.answers.select("sum(up_votes) total_up_votes").first
return (data.total_up_votes.present? && data.total_up_votes >= 10)
end
end

The query may execute in MySQL, but I doubt that it "works fine". It returns only one row, so the ordering is meaningless.
Your question is vague on what you actually want to do, but this should produce the same results as your query, in both databases:
SELECT sum(up_votes) as total_up_votes
FROM answers
WHERE user_id = 100;

Related

Rails query executes 2 queries

I have a simple rails query like
a = A.where(type: 'user')
if a.count > 1
#Log Information
end
return a
Rails does lazy loading where it doesn't query the database unless some operation on the result set is executed. This is a fine behavior. But in my case rails ends up executing 2 queries because I call a.count before operating on a
SELECT COUNT(*) FROM `a` WHERE `a`.`type` = 'user';
SELECT `a`.* FROM `a` WHERE `a`.`type` = 'user';
Is there any way I can ask rails to perform the query immediately so that only the second query is executed and the count is returned from the dataset.
You can force the results into an array. I think that to_a will work for that, but entries is a clearer way express that intention since its job is to iterate over the items in an Enumerable and return an array of the enumerated results.
a = A.where(type: 'user').entries
if a.count > 1
#Log Information
end
return a

using a function in where clause for SQL

I'm trying to use a function in the where clause to get the previous business date in order to calculate the delta of a column in the table
I'm using the following query which isn't working:
select db1.x, db2.date, db1.date, db1.y as ValNow, db2.y as ValPrevious
from db db1, db db2
where db1.x = 275305
and db1.x = db2.x
and (dbo.getLastBusinessDate(db1.date) = db2.date)
order by db1.date
I need to use the function because it will include special dates where there are no values
EDIT:
Sorry for the vague message the error that I'm getting is
Msg 557, Level 16, State 2, Line 1
Only functions and some extended stored procedures can be executed from within a function.
I just want to display the values side by side right now to confirm that the sql statement is working correctly, I planned to use the following statement to calculate delta
select db1.date, db1.x, (db1.y - db2.y) as delta , DAY(db1.date), DAY(db2.date)
from
db db1
inner JOIN db db2 on db1.x = db2.x and dbo.getLastBusinessDate(db1.date) = db2.date
order by date desc
First you use LEFT JOIN because first date doesnt have "previous date". You may want handle that null.
Then in the join you use doble condition, first db1.x = db2.x and db1.date > db2.date to make sure you match an early date.
In the where you have to make sure you select the exact previous date.
This should work in both MySql or SqlServer, but in sql server you can use window function for a better result.
SELECT
db1.x,
db2.date,
db1.date,
db1.y as ValNow,
db2.y as ValPrevious
FROM
db db1
LEFT JOIN db db2
ON db1.x = db2.x
AND db1.date > db2.date
WHERE db1.x = 275305
AND not exist (SELECT db3.date
FROM db db3
WHERE db3.date > db2.date
AND db3.date < db1.date)
ORDER BY db1.date

Error Converting MySQL Query to SQL Server

Trying to convert below query into SQL, query works fine on MySQL. Problem seems to be the GROUP BY area. Even when I use just 1 GROUP BY field I get same error. Using query in InformaticaCloud.
ERROR
"the FROM Config_21Cent WHERE resp_ind = 'Insurance' GROUP BY
resp_Ind;;] is empty in JDBC connection:
[jdbc:informatica:sqlserver://cbo-aps-inrpt03:1433;DatabaseName=SalesForce]."
SELECT sum(Cast(Resp_Ins_Open_dol AS decimal(10,2))) as baltotal,
carrier_code,
carrier_name,
carrier_grouping,
collector_name,
dataset_loaded,
docnum,
envoy_payer_id,
loc,
market,
master_payor_grouping,
plan_class,
plan_name,
resp_ins,
resp_ind,
resp_payor_grouping,
Resp_Plan_Type,
rspphone,
state
FROM Config_21Cent
WHERE resp_ind = 'Insurance'
GROUP BY
(resp_ins + resp_payor_grouping +
carrier_code + state + Collector_Name);
Your entire query isn't going to work. The group by statement contains a single expression, the summation of a bunch of fields. The select statement contains zillions of columns without aggregates. Perhaps you intend for something like this:
select resp_ins, resp_payor_grouping, carrier_code, state, Collector_Name,
sum(Cast(Resp_Ins_Open_dol AS decimal(10,2))) as baltotal
from Config_21Cent
WHERE resp_ind = 'Insurance'
GROUP BY resp_ins, resp_payor_grouping, carrier_code, state, Collector_Name;
THis will work in both databases.
The columns in SELECT statement must be a subset (not proper subset but subset) of columns in 'GROUP BY' statement. There is no such restriction on aggregates in SELECT statement though. There could be any number of aggregates; aggregates even on columns not in GROUP BY statement can be included.

Using Django Count() with conditional lookup types

So I'm trying to aggregate exam data, and because the database lives on another server I'm trying to reduce this to as few database calls as possible.
I have this model (whose corresponding table is in a mySQL database if that matters):
class Exam(models.Model):
submitted = models.BooleanField(default=False)
score = models.DecimalField(default=Decimal(0))
And this query:
>>> exam_models.Exam.objects\
... .using("exam_datebase")\
... .aggregate(average=Avg("score"),
... total=Count("submitted"))
{'average': 22.251082, 'total': 231}
What I'm looking for is a way to also retrieve the number of passed exams, something along the lines of:
>>> exam_models.Exam.objects\
... .using("exam_datebase")\
... .aggregate(average=Avg("score"),
... total=Count("submitted"))
... passed=Count("score__gte=80"))
{'average': 22.251082, 'total': 231, 'passed': 42}
I know I can just send another query using .filter(score__gte=80).count(), but I was really hoping to get both the total count and the passing count on the same aggregate. Any ideas?
You are either going to need two queries, or do the aggregation manually.
To see why, let's consider the underlying SQL that Django generates and uses to query the database.
Exam.objects.aggregate(average=Avg("score"), total=Count("submitted"))
roughly translates to
SELECT AVG(score), COUNT(submitted)
FROM exam
The "Count" part of the aggregate is applying to the SELECT clause in the underlying sql query. But if we want to include only scores greater than some value, the SQL query would need to look something like this:
SELECT AVG(score), COUNT(submitted)
FROM exam
WHERE score > 80
Filtering Exams with a particular "score" is applies to the WHERE or HAVING clause of the underlying SQL statement.
Unfortunately, there is not really a way to combine these two things. So, you are stuck doing two queries.
Having said all that, if you REALLY want to do a single query, one option is to just do the aggregation in your python code:
exams = Exam.objects.all()
total_score = 0
total_submitted = 0
passed = 0
for exam in exams:
total_score += exam.score
if exam.submitted:
total_submitted += 1
if exam.score >= 80:
passed += 1
exam_aggregates = {
'average': total_score / len(exams),
'submitted': total_submitted,
'passed': passed,
}

from sql query to mysql equivalent

Please, i have this query which is in sql
select sum(lhd.sasih)-sum(lhd.sasid) as sasi,lhd.kartllg as kartllg
from e2013..levizjehd lhd,supersick_db..produkt as prod
where lhd.kartllg=prod.kodfinance
group by lhd.kartllg
I need to write it's equivalent but in mysql...
I get this error:
Invalid object name 'e2013..levizjehd'.
What i need is to translate it in mysql query, but i don't know what .. stand for in sql.
I'd appreciate some help please.
How i connect
$host="192.168.10.250\\f501";
$uid="sa";
$passVal="";
$database="SUPERSICK_DB";
$objConnect = odbc_connect("Driver={SQL Server};Server=$host;Database=$database;",$uid, $passVal ) or die("Connection could not established");
Thanks!
Seems like it is referring the database name. So like 'e2013' is one DB and 'supersick_db' is another. The first contains the 'levizjeh' table the other one the 'produkt' table.
If you have both tables inside the same mysql than you can skip the name and the .. altogether.
SELECT SUM(lhd.sasih)-SUM(lhd.sasid) AS sasi, lhd.kartllg AS kartllg
FROM levizjehd lhd, produkt prod
WHERE lhd.kartllg = prod.kodfinance
GROUP BY lhd.kartllg
You can improve the query like this:
SELECT SUM(lhd.sasih)-SUM(lhd.sasid) AS sasi, lhd.kartllg AS kartllg
FROM levizjehd lhd
INNER JOIN produkt prod ON lhd.kartllg = prod.kodfinance
GROUP BY lhd.kartllg
I think Angelo's covered the question but note that the following aren't equivalent:
SUM(lhd.sasih) - SUM(lhd.sasid)
SUM(lhd.sasih - ldh.sasid)
These expressions can potentially return different results if either column is nullable: aggregates ignore nulls. E.g. if row one is {10, null} and row two is {100, 50} the first returns 10 + 10 - 50; the second 100 - 50.