When I use MySQL, the following query runs clean.
SELECT 1 as num1, (select(num1 + 1)) as num2
But PostgreSQL is returning an error.
ERROR: column "num1" does not exist
Why is it responding differently?
The question shouldn't be why does Postgres not support this syntax, but why MySQL does. In most RDBMSs, aliases are only resolved after the query is executed, so you can't use them from within the query that declares them. E.g., the more common usecase - you cannot use a column alias in a where clause of the query/table-element that declared it.
One way around this is to use subqueries:
SELECT num1, num1 + 1 AS num2
FROM (SELECT 1 AS num1) t
you should use PostgreSQL syntax , because PgSql does not support sub query this way, try this
WITH tblcontent AS (SELECT 1 as num1)
SELECT num1, num1 + 1 AS num2 from tblcontent
I can't find any good source, but I am quite sure that the standard does not require aliases of projected columns to be visible inside a correlated sub query. I just tried it in SQL Server and Oracle, and both of them seem to agree with PostgreSQL here, rejecting using x in a correlated sub query, no matter in which clause of the outer select it is located.
It is similar to how MySQL allows the following query:
SELECT a + 1 x
FROM t
ORDER BY x + 1
but SQL Server and Postgres do not. MySQL seems to be more permissive with regard to using aliases in various clauses than the standard requires.
Related
In MSSQL, I have a query something like:
WITH temp AS (
SELECT
*
FROM
xx.xxxx
)
But WITH temp AS () isn't supported in MySQL syntax, I wonder what the equivalent syntax should be in MySQL Workbench? Thanks.
Below is a screenshot of the syntax error:
If you have MySQL 5.x and you need to adapt the query which contains CTE, then convert
WITH cte AS (cte query text)
SELECT ...
FROM cte
...
to
SELECT ...
FROM (cte query text) cte
...
If there is more than one CTE then perform this substitution with accuracy from latter CTE to former one (you may need to use multiple copies of some CTE subquery text - this is a norma).
I have a question similar to the one found here: How to find rows in SQL that start with the same string (similar rows)?, and this solution works in MySQL 5.6 but not 5.7.
I have a database (t) with multiple columns, the important ones being id and filepath, and what I am trying to accomplish is retrieving all the file paths which have the same last 5 characters. The following works in MySQL5.6, and the second SELECT works fine in 5.7:
SELECT id, filepath FROM t
WHERE SUBSTRING(filepath, -5) IN
(
SELECT SUBSTRING(filepath, -5)
FROM t
GROUP BY SUBSTRING(filepath, -5)
HAVING COUNT(*) > 1
)
But when I try to run it on 5.7 I get the error
Expression #1 of HAVING clause is not in GROUP BY clause and contains
nonaggregated column 't.filepath' which is not functionally dependent on
columns in GROUP BY clause; this is incompatible with
sql_mode=only_full_group_by
Sample data:
id filepath
1 /Desktop/file1.txt
2 /Desktop/file2.txt
3 /Desktop/file1.txt
and I would want to return the rows with id 1 and 3. How can I fix this for MySQL5.7?
EDIT: Also can anybody point me in the right direction for the SQL to remove the duplicates? So I would want to remove the entry for id 3 but keep the entry for id 1 and 2.
Please read the mysql documentation on the subject GROUP BY and sql_mode only_full_group_by (like your error message says):
https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
I think changing the inner query to this might fix the problem:
SELECT SUBSTRING(filepath, -5) AS fpath
FROM t
GROUP BY fpath
HAVING COUNT(fpath) > 1
Edit:
As to your question of why adding the "AS fpath" works:
Adding the alias "fpath" is just a clean way to do this. The point of ONLY_FULL_GROUP_BY is that each field you use in the SELECT, HAVING, or ORDER BY must also be in the GROUP BY.
So I added the fpath-alias for multiple reasons:
For performance: The query you wrote had SUBSTRING(filepath, -5) twice, which
is bad for performance. Mysql has to execute that SUBSTRING call twice,
while in my case it has to do it only once (per row).
To fix the group-by issue: You had COUNT() in the having, but "" was not in your GROUP BY statement (I'm not even sure whether that would be possible). You had to count "something", so since "fpath" was in your SELECT and in your GROUP BY, using that as your COUNT() would fix the problem.
I prefer not to put subqueries in an IN() predicate because MySQL tends to run the subquery many times.
You can write the query differently to put the subquery in the FROM clause as a derived table. That will make MySQL run the subquery just once.
SELECT id, filepath
FROM (
SELECT SUBSTRING(filepath, -5) AS suffix, COUNT(*) AS count
FROM t
GROUP BY suffix
HAVING count > 1
) AS t1
JOIN t AS t2 ON SUBSTRING(t2.filepath, -5) = t1.suffix
This is bound to do a table-scan though, so it's going to be a costly query. It can't use an index when doing a substring comparison like that.
To optimize this, you might create a virtual column with an index.
ALTER TABLE t
ADD COLUMN filepath_last VARCHAR(10) AS (SUBSTRING_INDEX(filepath, '/', -1)),
ADD KEY (filepath_last);
Then you can query it like this, and at least the subquery uses an index:
SELECT id, filepath
FROM (
SELECT filepath_last, COUNT(*) AS count
FROM t
GROUP BY filepath_last
HAVING count > 1
) AS t1
STRAIGHT_JOIN t AS t2 ON t2.filepath_last = t1.filepath_last
The solution that ended up working for me was found here: Disable ONLY_FULL_GROUP_BY
I ran SELECT ##sql_mode then SET ##sql_mode = followed by a string containing all the values returned by the first query except for only_full_group_by, but I'm still interested in how this is to be accomplished without changing the SQL settings.
I want to run a case statement that runs different SELECT Statements Based on a condition in Spark SQL but not able to get the Syntax Right .
My SQL statement looks like this
registerTable(sql="SELECT CASE WHEN typedKeyword > '' THEN (SELECT * FROM `temp.sdf0` WHERE originalKeyword > ''AND keyword > '' AND deviceType = 'devicetype' ) ELSE (SELECT * FROM `temp.tes` WHERE originalKeyword > ''AND keyword > '' ) END ",alias="temp.test")
I don't know if CASE statement is supported in spark SQL so How can one achieve this
I've worked in nearly a dozen SQL and SQL-like dialects and I've never seen syntax like that. It looks like there's a core misunderstanding of what SQL clauses are supposed to do what.
The SELECT clause is for describing a projection of scalar elements. In many dialects you can issue subqueries - sometimes even correlated subqueries - in this clause, but you always must apply an operator that converts the result into a scalar value. For example:
SELECT (CASE WHEN EXISTS (SELECT foo FROM tbl) THEN 1 ELSE 0 END)
Here the "EXISTS" operator converts the uncorrelated subquery into a scalar boolean, so it's legal.
The lack of a FROM clause in the top level query is also a big red flag. It, or some analogue like Oracle's "dual", is legal in about half of the dialects I've seen, but if what you're trying to do is dynamically switch between two queries, you're almost certainly doing it wrong. juergen is right - what you probably meant to do is use 2 different queries.
SQL Server 2008 R2 - Query from 2014 SSMS but fails from code as well.
Strange - first reference to table B works, second fails with an 'Invalid object B' error. What am I doing wrong? GO's don't help.
WITH B as (SELECT BatchOutId, SettleMerchantCode, BatchDate, BatchStatusCode, BatchTransCnt, BatchTotAmt, BatchAdjustAmt, BatchAdjustCnt
FROM MAF01
GROUP BY BatchOutId, SettleMerchantCode, BatchDate, BatchStatusCode, BatchTransCnt, BatchTotAmt, BatchAdjustAmt, BatchAdjustCnt)
SELECT * FROM B ORDER BY BatchOutId DESC
SELECT * FROM B ORDER BY BatchOutId DESC
This is as expected.
CTEs are only in scope for the next statement. They are just named queries.
You would need to either
Repeat the definition of the CTE.
Move the definition out into a view or inline function.
Materialise the results into a temp table.
Depending on what you were expecting to happen.
A cte is only valid for one query, not an entire batch. So once you do the first SELECT * FROM B, that query is finished. The next query no longer has access to the cte that the first query used.
I know this has to be duplicate
You can have multiple CTE but only one statement
The two Select are two statements
If you use a #temp then you can have more than one statement
I have a problem with Aliased Columns in MySQL!
My Query:
SELECT Price AS Pr, (Pr*10/100) FROM MyTable;
MySQL WorkBench Error: UnKnown Column 'Pr' in Field List !!!
I tested my query in W3Schools with no error !
I tested my query in W3Schools with no error!
This doesn't prove that your query is valid.
You can only use aliases in GROUP BY, ORDER BY or HAVING clauses. Your usage variant is not allowed, because the value of alias is not known when MySQL is selecting the 2-nd column.
I've got a suspicion that W3Schools uses MS Access to run user queries, and MS Access does allow such atrocity as referencing column aliases in a SELECT clause that are defined in the same SELECT clause.
The standard doesn't allow this and MySQL does follow standard in this particular case.
As for solution to your problem, I can see two options.
The more generic solution, which would run in probably any SQL product, would be to use a derived table:
SELECT
Pr,
(Pr * 10 / 100) AS SomethingElse
FROM
(
SELECT
SomeComplexExpression AS Pr
FROM MyTable
) AS sub
;
The other option would be to use a variable, which is MySQL-specific:
SELECT
#Pr := SomeComplexExpression AS Pr,
(#Pr * 10 / 100) AS SomethingElse
FROM MyTable
;
Finally, if you need to test/demonstrate if something can/cannot work in MySQL, I'd recommend using SQL Fiddle.