I am new to COALESCE function in REDSHIFT. I ran below four queries in mysql and Redshift.
1st and 2nd query executed as expected in both mysql and redshift. But for 3rd and 4th query I am getting two different results in mysql and Redshift. How does this behave?
select COALESCE(null,null,1) -> 1
select COALESCE(null,null,'John') -> 1
select COALESCE(null,null,1,'John') -> (Redshift : error , mysql:1)
select COALESCE(null,null,'John',1) -> (Redshift: error, mysql:John)
Also this query should give error in mysql but it has succeeded
Any help is appreciated
Amazon Redshift Database Developer Guide claims:
An NVL expression is identical to a COALESCE expression. NVL and
COALESCE are synonyms.
Syntax
NVL | COALESCE ( expression, expression, ... )
An NVL or COALESCE expression returns the value of the first expression
in the list that is not null. If all expressions are null, the result
is null. When a non-null value is found, the remaining expressions in
the list are not evaluated.
This type of expression is useful when you want to return a backup
value for something when the preferred value is missing or null. For
example, a query might return one of three phone numbers (cell, home,
or work, in that order), whichever is found first in the table (not
null).
If you obtain the error this may mean that the returned value datatype do not match the datatype of recordset field or any another structure which must accept the returned value.
PS. Will you show error messages?
Though it is not written in the documentation, but coalesce works on the compatible data types. Integer and varchar cannot be compared.
The error becomes more evident when you provide column name instead of hard-code values. Try executing this:
select coalesce(integer_column, varchar_column) from a_table;
You would get an error saying something like this:
coalesce types integer and varchar cannot be matched.
Related
I have database ready with data as per below screenshot, green column is customized column which I need to generate while querying data from SQL/Oracle.
Logic: If Actual_Completion_Date is not an empty/null, then bring
Actual_Completion_Date into Completion_Date else get
Schedule_Completion_Date in Completion_Date column.
Is there any way, where I should write If statement while defining column names in SQL query without stored procedure help.
If both date field contains NULL value then use simply COALESCE(). IF first one is NULL then second one value will show if it's not NULL. If first one is not null then will sshow first one value.
SELECT Activity_Details, Actual_Completion_Date
, Schedule_Completion_Date
, COALESCE(Actual_Completion_Date, Schedule_Completion_Date) AS Completion_Date
FROM tbl;
You can simply do this in the SELECT clause of your query. For example using the IF() function like this in mysql:
SELECT Activity_Details, Actual_Completion_Date, Schedule_Completion_Date, IF(Actual_Completion_Date IS NOT NULL, Actual_Completion_Date, Schedule_Completion_Date) AS Completion_Date
FROM tbl;
The IF function takes a condition that should return True or False as the first argument. If the condition evaluates to true, the second argument is returned and if it evaluates to false, the third.
In Oracle or Microsoft SQL server you would do something similar in the SELECT clause of your query, but using CASE WHEN ... THEN ... ELSE ... END
Oracle (and MySQL) both support generated columns. That means that you can add the logic as part of the table definition. I'm not sure if this is what you are asking for, but in Oracle, this looks like:
alter table t add column completion_date date generated always as
(coalesce(Actual_Completion_Date, Schedule_Completion_Date)) virtual;
This would be calculated when the table is queried and available to any query that uses the table.
This case is similar to: S.O Question; mySQL returns all rows when field=0, and the Accepted answer was a very simple trick, to souround the ZERO with single quotes
FROM:
SELECT * FROM table WHERE email=0
TO:
SELECT * FROM table WHERE email='0'
However, my case is slightly different in that my Query is something like:
SELECT * FROM table WHERE email=(
SELECT my_column_value FROM myTable WHERE my_column_value=0 AND user_id =15 LIMIT 1 )
Which in a sense, becomes like simply saying: SELECT * FROM table WHERE email=0, but now with a Second Query.
PLEASE NOTE: It is a MUST that I use the SECOND QUERY.
When I tried: SELECT * FROM table WHERE email='( SELECT my_column_value FROM myTable WHERE my_column_value=0 LIMIT 1 )' (Notice the Single Quotes on the second query)
MySql SCREAMED Errors near '(.
How can this be achieved
Any Suggestion is highly honored
EDIT1: For a visual perspective of the Query
See the STEN_TB here: http://snag.gy/Rq8dq.jpg
Now, the main aim is to get the sten_h where rawscore_h = 0;
The CURRENT QUERY as a whole.
SELECT sten_h
FROM sten_tb
WHERE rawscore_h = (
SELECT `for_print_stens_rowscore`
FROM `for_print_stens_tb`
WHERE `for_print_stens_student_id` =3
AND `for_print_stens_factor_name` = 'Factor H' )
The result of the Second Query can be any number including ZERO.
Any number from >=1 Works and returns a single corresponding value from sten_h. Only =0 does not Work, it returns all rows
That's the issue.
CORRECT ANSWER OR SOLUTION FOR THIS
Just in case someone ends up in this paradox, the Accepted answer has it all.
SEE STEN_TB: http://snag.gy/Rq8dq.jpg
SEE The desired Query result here: http://snag.gy/wa4yA.jpg
I believe your issue is with implicit datatype conversions. You can make those datatype conversions explicit, to gain control.
(The "trick" with wrapping a literal 0 in single quotes, that makes the literal a string literal, rather than a numeric.)
In the more general case, you can use a CAST or CONVERT function to explicitly specify a datatype conversion. You can use an expression in place of a column name, wherever you need to...
For example, to get the value returned by my_column_value to match the datatype of the email column, assuming email is character type, something like:
... email = (SELECT CONVERT(my_column_value,CHAR(255)) FROM myTable WHERE ...
or, to get the a literal integer value to be a string value:
... FROM myTable WHERE my_column_value = CONVERT(0,CHAR(30)) ...
If email and my_column_value are just indicating true or false then they should almost certainly be both BIT NOT NULL or other two-value type that your schema uses for booleans. (Your ORM may use a particular one.) Casting is frequently a hack made necessary by a poor design.
If it should be a particular user then you shouldn't use LIMIT because tables are unordered and that doesn't return a particular user. Explain in your question what your query is supposed to return including exactly what you mean by "15th".
(Having all those similar columns is bad design: rawscore_a, sten_a, rawscore_b, sten_b,... . Use a table with two columns: rawscore, sten.)
I'm working with iReport Designer and JasperServer 5.6 on a MySQL database and I'm trying to make my report return all results when the parameter is null.
I've been looking at the documentation here: http://jasperreports.sourceforge.net/sample.reference/query/, which has been quite helpful except it doesn't have what I want. The closest I've gotten is here in the documentation:
The $X{EQUAL, column_name, parameter_name} clause function
The function expects three mandatory clause tokens:
The first token represents the function ID and always takes the fixed value EQUAL.
The second token is the SQL column (or column combination) to be used in the clause.
The third token is the name of the report parameter that contains the value to compare to.
If the parameter's value is not null, the function constructs a
= ? clause. If the parameter's value is null, the
function generates a IS NULL clause.
All the parameters I'm inputting are the id's of the records I'd like to see, so when I use this I get no results because an id or the Primary Key cannot be null.
Ex.
SELECT *
FROM User
WHERE $X{EQUAL, user.id, user_id}
Inputting 1 will return user id 1 and inputting nothing, or null, will return me nothing. What I want it to return instead is all users in the table.
Is there an easy fix to this problem, like having this function return IS NOT NULL when this happens? Is there something else in JasperServer or iReports that will help me or is there something I can do in SQL that will ignore a WHERE clause when I have this parameter set to null?
You can use the below logic in your query's WHERE clause to achieve what you are asking (this works in postgres, but it should work in MySQL as well):
where (($P{parameter1} is null) or (user.id = $P{parameter1}))
If the parameter is null the first part of the OR comparator will return true, and the query will ignore the rest of the expression, which should give you all users in the user table. If it is not null, it will skip over the first part and execute the query for the user.id passed to the parameter.
Hope this helps!
What I'm Using: The most recent MySQL on Ubuntu 12.
The Set Up: Suppose I have a table "EmployeePayment" with "Name" and "Hours" for each employee. Suppose I already have it populated with values.
The Question: When I use the command
select * from EmployeePayment where Name in ('');
I get the empty set, as I'd expect. But, when I use
select * from EmployeePayment where Name in ('' or '');
I get the entire table returned. Moreover, if I'm picky and put in the command
select Name, SUM(Hours) from EmployeePayment where Name in ('' or '');
then it only returns whatever is the top name from the table. What's happening with this "in" command?
First off, you need to get rid of the or, the proper syntax for the in clause uses commas to separate the possibilities, such as:
sql> select name from people where status in ('intelligent', 'good looking')
pax
1 row returned
What your current variant is doing is applying the or operator to give you a one-element in-list. See here for more detail.
The reason why you're only getting one row for the aggregated query is because you have no group by clause, so you're grouping all rows. Most DBMS' would then complain about having a non-aggregated column that isn't part of the grouping, but MySQL is a bit fancy-free and footloose with the rules in that regard.
It's obviously grouping over the whole table (as it should) but applying some default aggregating function to the name (which it probably shouldn't, but does according to its documentation).
This MySQL extension is covered here but heed the warning: MySQL can choose any of the myriad possible values for these non-aggregated, non-group-by columns, so it's more useful when you know that all the rows in a given group share the same value for the column.
You're effectively doing this:
select * from EmployeePayment where Name in (0);
The OR expression evaluates to 0, and WHERE Name IN (0); returns all rows. You have to use the proper IN syntax as suggested in the other answers:
SELECT * FROM EmployeePayment WHERE Name IN ('foo', 'bar');
IN uses comma separated values, for example: WHERE Name IN ('tim','beth')
So try WHERE Name IN ('','');
But more importantly, why would you want to check where a value is empty or empty? Or was that just to get the question across?
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_in
When I execute this query with MATCH AGAINST using MySql (see Query 1st) the issue in this query they has generated an error like this (see error) or when I execute the same query with = they executed normally(see Query 2nd).
My question is what am I doing wrong with against statement?
Query 1st
SELECT (SELECT COUNT(up.`user_id`)
FROM `users_post` up WHERE MATCH (up.`user_id`) AGAINST (uf.`user_id`))
AS user_count
FROM `users` uf
Error
enter code hereError Code : 1210
Incorrect arguments to AGAINST
(0 ms taken)
Update
Query 2nd
SELECT
(SELECT COUNT(up.`user_id`)
FROM `users_post` up WHERE up.`user_id` = uf.`user_id`)
AS user_count
FROM `users` uf
The problem is that the argument for AGAINST must be a literal string, for example 'Fred'. It is not allowed to use a column name like uf.user_id.
MATCH (up.`user_id`) AGAINST (uf.`user_id`)
-- ^^^^^^^^^^^^ not allowed!
From the documentation:
The search string must be a literal string, not a variable or a column name.
You probably need to use LIKE instead of MATCH, though you should note that it will be much slower.