sums return String, only with postgresql - mysql

I am migrating a database from mysql to postgres. The migration itself was ok, following the postgres documentation.
Right now, I'm fixing our specific mysql queries.
In some point, we have now something like this:
select(%(
SUM(CASE WHEN income THEN value ELSE 0 END) AS rents,
SUM(CASE WHEN not income THEN value ELSE 0 END) AS expenses
))
In mysql, it was a sum(if(incomes, value, 0)) etc, and it was working as expected.
With PG, it returns a string instead of a numeric.
I already checked the database and the data type is correct.
What can I do, besides cast to_d or to_f?
EDIT: the complete query:
SELECT
SUM(CASE WHEN income THEN value ELSE 0 END) AS rents,
SUM(CASE WHEN not income THEN value ELSE 0 END) AS expenses
FROM "transactions"
WHERE "transactions"."type" IN ('Transaction')
AND "transactions"."user_id" = 1
AND "transactions"."paid" = 't'
AND (transactions.date between '2013-09-01' and '2013-09-30')
LIMIT 1

As far as I know, using .to_f, .to_i or whatever is the answer - the Rails PostGres adapter seems adamant that everything is a String unless it's an ActiveRecord model.
See: connection.select_value only returns strings in postgres with pg gem
I don't particularly approve of this, but it is, as the saying goes, 'working as intended'.

Related

SQL CASE Statement Error while checking conditions

The scenario is that i have two columns one is Quantity and other is Type. Now what i am trying to do is check if type is "rec" then it take all the values from quantity and add them and if the type is "issue" then it will get only those fields whose type is receiving and add them all on the basis of ITEM ID. The SQL Query i have written is here:
SELECT f.`Itemm_ID`,ABS(SUM(f.`Quantity`)) AS recieving, TYPE ,
(CASE
WHEN f.`Type` = 'issue'
THEN ABS(SUM(f.`Quantity`))
END)
FROM stock_journal AS f
WHERE f.`Itemm_ID`='1'
Now the thing is everything is working fine except CASE statement which is returning null.
Please help me in resolving my issue. Thank you
It seems that you need in
SELECT f.`Itemm_ID`,
ABS(SUM(f.`Quantity`)) AS recieving,
TYPE,
ABS(SUM(CASE WHEN f.`Type` = 'issue'
THEN f.`Quantity`
ELSE 0
END))
FROM stock_journal AS f
WHERE f.`Itemm_ID`='1'
PS. Does f.Quantity may be negative? If not then ABS() is excess. If it may then ABS() must wrap inner f.Quantity, not the whole SUM(), maybe.
PPS. TYPE in output is formally incorrect (contradicts with ONLY_FULL_GROUP_BY), I'd recommend wrap it with ANY_VALUE().
i didn't get your recommendation of wrapping type with value can you please elaborate more.
I mean that (maybe, I'm not sure) you need
SELECT f.`Itemm_ID`,
SUM(ABS(f.`Quantity`)) AS recieving,
TYPE,
SUM(CASE WHEN f.`Type` = 'issue'
THEN ABS(f.`Quantity`)
ELSE 0
END)
FROM stock_journal AS f
WHERE f.`Itemm_ID`='1'
Have you checked syntax for CASE I think you are missing ELSE part in the query
Eg:-
SELECT OrderID, Quantity,
CASE
WHEN Quantity > 30 THEN "The quantity is greater than 30"
WHEN Quantity = 30 THEN "The quantity is 30"
ELSE "The quantity is under 30"
END
FROM OrderDetails;
check here for syntax

SQL - sum operations within case when statement

I need to aggregate some sessions by day, country etc. The table has a transaction amount for each session (in local currency) and a field with the exchange_rate to EUR for the time of the transaction. Like this:
amount | currency | exchange_rate | date | country
I ran sum(amount/exchange_rate), however, for roughly 0.5% of the rows the value for exchange_rate is 0 and therefore it throws the error "cannot divide by 0".
I tried to run it with case when:
sum(case when exchange_rate = 0 then sum(amount) else sum(amount/exchange_rate) end) as volume
But apparently nested sum's are not allowed. Does anybody have an idea as to how I can get the result the above should logically produce, but without nested sums in a case when statement?
Assuming that an exchange rate of 0 indicates that the amount is in EUR currency already, you can do:
sum(amount / case when exchange_rate = 0 then 1 else exchange_rate end)
I think you want:
sum(case when exchange_rate = 0 then amount else amount/exchange_rate end) as volume
Or for a bit less typing:
sum(amount / coalesce(nullif(exchange_rate, 0), 1)) as volume
Essentially you want to consider the exchange rate as 1 when it's zero. You can do:
sum(case when exchange_rate = 0
then amount
else amount/exchange_rate
end
) as volume

Use a generated column in MariaDB 5.5.52

I have a valid sql statement that looks like this:
SELECT SUM(CASE WHEN faell_art='monatlich' THEN betrag*12 END) + SUM(CASE WHEN faell_art='vierteljährlich' THEN betrag*4 END) + SUM(CASE WHEN faell_art='halbjährlich' THEN betrag*2 END) + SUM(CASE WHEN faell_art='jährlich' THEN betrag END) as total FROM banking
Now I want to create a generated column which does exactly the same. I tried this statement:
ALTER TABLE `banking` ADD `test` DECIMAL(10,2) AS (SUM(CASE WHEN faell_art='monatlich' THEN betrag*12 END) + SUM(CASE WHEN faell_art='vierteljährlich' THEN betrag*4 END) + SUM(CASE WHEN faell_art='halbjährlich' THEN betrag*2 END) + SUM(CASE WHEN faell_art='jährlich' THEN betrag END)) AFTER `kommentar`;
However it doesn´t work ("#1901 - Function or expression is not allowed for column 'test'").
Any help? Thx :-)
There is a limitation:
subqueries or anything that depends on data outside the row are not
allowed (these are not deterministic because the underlying data can
change).
All aggregate functions (SUM,...) operate with other records in the table.
Virtual (Computed) Columns.
So, that generated column cannot be created. Or, you could create a view.

DATEDIFF SQL Query

I am at the final stage of my project and have the problem to find if a job is overdue. I link this to priority for example if a job has a priority of 1 it must be complete in 1 day, a priority of 4 then 4 days.
I have come up with a CASE however this doesn't seem to work any help would be appreciated.
SELECT `defect_Id`,`Overtasked`
WHERE
CASE DATEDIFF(DD,`date_Investigaton` - `CURRENT_DATE()`) >= `priority` AS Overtasked
THEN `Overtasked` == 'YES'
ELSE `Overtasked` == 'NO'
END
Solution
`SELECT defect_Id,
CASE WHEN DATEDIFF(date_Investigated, CURDATE()) >= priority
THEN 'YES'
ELSE 'NO'
END AS Overtasked
FROM defect_report
WHERE defect_Id = '82'`
Appreciate the guidance you guys give!
You are completely mixing up SQL dialects and even there are syntax errors.
Assuming you are talking about MS SQL Server let's try this:
SELECT defect_Id,
CASE WHEN DATEDIFF(DD, date_Investigaton, getdate()) >= priority
THEN 'YES'
ELSE 'NO'
END AS Overtasked
FROM <YourTable>
WHERE <YourWhereIfAny>
If date_Investigation is a DATE column, the subtraction date_Investigation - CURRENT_DATE() produces the number of days you need.
Otherwise (if it is a DATETIME, for example) both operands are converted to float and the result is something you are totally not expecting. For such situations use the DATEDIFF() function. It interprets its arguments as DATE (ignores the time part) and returns the integer number of days between the two dates.
Your query should be like:
SELECT
`defect_Id`,
IF (DATEDIFF(`date_Investigaton`, CURRENT_DATE()) >= `priority`, 'YES', 'NO')
AS `Overtasked`
FROM [...your table name here...]
WHERE [...conditions...]
Replace the parts in square brackets ([...]) with the name of the table where to get the data from and some conditions to limit the number of returned rows (otherwise it will get the entire table which, most probably, is not what you want).
Btw, CURRENT_DATE() is also a function. If you write it in backquotes (``), MySQL will try to find a column with this name and it will fail.
Read the accepted answer for this question. It explains when to use back ticks, single quotes or double quotes in MySQL (and partially in PHP).

Using Sum inside a Case statement in MySQL

I am having problem in MySQL adding three values, this should be simple right?
I have code that selects values from a column based upon the value of a second column, I use a case statement like this:
Select
Max(Case
When Table1.costcode Like '%Costcode1%'
Then Table1.costs
Else Null End) As 'Costcode1',
Max(Case
When Table1.costcode Like '%Costcode2%'
Then Table1.costs
Else Null End) As 'Costcode2',
Max(Case
When Table1.costcode Like '%Costcode3%'
Then Table1.costs
Else Null End) As 'Costcode3',
(Case
When Table1.costcode In ('%Costcode1%','%Costcode2%','%Costcode3%')
Then Sum(Table1.costs)
Else Null End) As 'Total Cost',
From Table1
the first three Case statements work fine and all return values (these are held in the database as negative numbers e.g. -13624.00), however the Total Cost Case just returns Null...
The column Table1.costcode includes many other codes as well so I can't just sum all of the values without picking them out first.
It must be simple to sum these values, but obviously I'm missing something… Help, please :-)
Thanks
Try this -
SUM(Case Table1.costcode
When LIKE ('%Costcode1%') Then Table1.costs
When LIKE ('%Costcode2%') Then Table1.costs
When LIKE ('%Costcode3%') Then Table1.costs
Then Table1.costs
Else 0.00 End) As 'Total Cost'