SQLite: reuse quoted alias - sql

I'd like to reuse an alias that contains a non-alphabetic character in a query, something like:
SELECT 42 AS "the#answer", "the#answer"+8 AS "fifty";
Output I want: 42|50; output I get: 42|8.
I've tried almost every possible combination of quote types, and looked for documentation, but I can't seem to find a working solution.
Any idea?

SQL cannot refer to an alias from the same output clause in which it was introduced. (It has nothing to do with quoting, which only allows otherwise invalid identifiers; some SQL vendors would have thrown an error, but SQLite appears "more relaxed" in the handling of this case.)
You could use a nested query (sqlfiddle).
SELECT fortytwo, fortytwo + 8 as fifty
FROM (
SELECT 42 AS fortytwo)
This works because the referenced identifier, fortytwo, was introduced in a "previous" output clause.

Related

Decode not working

I can't seem to figure out why this won't work - can someone please help? This is part of a larger query, so I don't want to have to update the one that already exists - just wanna add to it -
SELECT INNERPART.*,
SUBSTR(status_remday, 1,1) AS COMPLETE,
**--this line shows if it is completed or not**
DECODE(SUBSTR(status_remday, 1,1),'Y','Complete','N','Incomplete', null) AS qualCompleted,
**--need this to show if the curriculum is complete or not, in it's own row. will eventually have about 10 or more qual_ids**
decode(INNERPART.qualID,'ENG_CURR_SAFETY CERT', qualCompleted) as SAFETY
FROM (Innerpart)
The problem is that the SQL syntax (the Oracle dialect, anyway) doesn't allow you to define an alias in a SELECT clause and then reference the same alias in the same SELECT clause (even if it's later in the clause).
You define qualCompleted as a DECODE, and then you reference qualCompleted in the second DECODE. That won't work.
If you don't want to define qualCompleted at one level and then wrap everything within an outer SELECT where you can reference that name, your other option is to use the first DECODE, as is (not by alias) in the second DECODE.
This:
decode(INNERPART.qualID,'ENG_CURR_SAFETY CERT', qualCompleted) as SAFETY
should instead be written as
decode(INNERPART.qualID,'ENG_CURR_SAFETY CERT',
DECODE(SUBSTR(status_remday, 1,1),'Y','Complete','N','Incomplete', null) )
as SAFETY
One more thing: by default, DECODE returns null if the first parameter is not matched in DECODE. So you don't actually need to give the last parameter (null) in your definition of qualCompleted.
EDIT: here is what the Oracle documentation says about column aliases.
Link: https://docs.oracle.com/database/121/SQLRF/statements_10002.htm#i2080424
c_alias Specify an alias for the column expression. Oracle Database will use this alias in the column heading of the result set.
The AS keyword is optional. The alias effectively renames the select
list item for the duration of the query. The alias can be used in
the order_by_clause but not other clauses in the query.
This means a few things. An alias like the qualCompleted you created cannot be used in the same query in the WHERE clause, GROUP BY, etc. - and not even in the SELECT clause where it was created. It can ONLY be used in the ORDER BY clause of the same query. Any other use must be in a surrounding, "outer" query. It also does mean, though, that you can use it in ORDER BY, if needed.
In your case, if you ONLY created qualCompleted so that you can reference it in another DECODE, and had no other use for it, then you don't even need to define it at all (since it doesn't help anyway); just define SAFETY directly as a nested call to DECODE.

Count Aggregate Dot Count Syntax (.count)

So I ran into what I thought was a bizarre error this morning when I accidentally referred to a non-existant "count" column in my CTE. Postgres was looking for a GROUP BY clause even though I didn't think I was doing an aggregate. A little more playing around and it appears the table.count is equivalent to a count star function. Consider the following:
SELECT
c.clinic_id,
c.count,
count(*) as count_star
FROM clinic_member c
GROUP BY
c.clinic_id
ORDER BY clinic_id;
This will generate results that look like this in my dataset:
Intrigued to understand what the actual Postgres syntax rules are, I tried searching the documentation for references to this syntax and was unable to find anything; just lots of documentation for count(*). Can anyone explain if this is valid SQL and whether there are other aggregate functions that can also be called similarily? Links to Postgres documentation would be awesome if they exist.
Note. This is on Postgres 9.5.9
It is valid Postgres syntax because in Postgres a function with a single argument that matches a table type can be called in two different ways:
Assuming a table name foo and a function named some_function with a single argument of type foo then the following:
select some_function(f)
from foo f;
is equivalent to
select f.some_function
from foo f;
The alias is actually not necessary:
select foo.some_function
from foo;
This is a result of the "object oriented" structure of Postgres.
count() can take any argument - including a row reference (=record) therefore
select count(f)
from foo f;
is equivalent to
select f.count
from foo f;
This is documented in the chapter about Function Calls in the manual:
A function that takes a single argument of composite type can optionally be called using field-selection syntax, and conversely field selection can be written in functional style. That is, the notations col(table) and table.col are interchangeable. This behavior is not SQL-standard but is provided in PostgreSQL because it allows use of functions to emulate “computed fields”. For more information see Section 8.16.5.

DB2 complex like

I have to write a select statement following the following pattern:
[A-Z][0-9][0-9][0-9][0-9][A-Z][0-9][0-9][0-9][0-9][0-9]
The only thing I'm sure of is that the first A-Z WILL be there. All the rest is optional and the optional part is the problem. I don't really know how I could do that.
Some example data:
B/0765/E 3
B/0765/E3
B/0764/A /02
B/0749/K
B/0768/
B/0784//02
B/0807/
My guess is that I best remove al the white spaces and the / in the data and then execute the select statement. But I'm having some problems writing the like pattern actually.. Anyone that could help me out?
The underlying reason for this is that I'm migrating a database. In the old database the values are just in 1 field but in the new one they are splitted into several fields but I first have to write a "control script" to know what records in the old database are not correct.
Even the following isn't working:
where someColumn LIKE '[a-zA-Z]%';
You can use Regular Expression via xQuery to define this pattern. There are many question in StackOverFlow that talk about patterns in DB2, and they have been solved with Regular Expressions.
DB2: find field value where first character is a lower case letter
Emulate REGEXP like behaviour in SQL

How to implement "like" in BigQuery?

I am trying to run a simple query making a restriction of like % in BigQuery, but LIKE is not in their syntax, so how can it be implemented?
You can use the REGEXP_MATCH function (see the query reference page):
REGEXP_MATCH('str', 'reg_exp')
Instead of using the % syntax used by LIKE, you should use regular expressions (detailed syntax definition here)
LIKE is officially supported in BigQuery Standard SQL -
https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#comparison_operators
And I think it also works in Legacy SQL!
REGEXP_MATCH returns true if str matches the regular expression. For string matching without regular expressions, use CONTAINS instead of REGEXP_MATCH.
https://developers.google.com/bigquery/docs/query-reference#stringfunctions
REGEXP_MATCH is great if you know how to use it, but for those who aren't sure there won't be any commonly used special characters such as '.','$' or '?' in the lookup string, you can use LEFT('str', numeric_expr) or RIGHT('str', numeric_expr).
ie if you had a list of names and wanted to return all those that are LIKE 'sa%'
you'd use:
select name from list where LEFT(name,2)='sa'; (with 2 being the length of 'sa')
Additionally, if you wanted to say where one column's values are LIKE another's, you could swap out the 2 for LENGTH(column_with_lookup_strings) and ='sa' for =column_with_lookup_strings, leaving it looking something like this:
select name from list where LEFT(name,LENGTH(column_with_lookup_strings))= column_with_lookup_strings;
https://cloud.google.com/bigquery/query-reference

Can scalar functions be applied before filtering when executing a SQL Statement?

I suppose I have always naively assumed that scalar functions in the select part of a SQL query will only get applied to the rows that meet all the criteria of the where clause.
Today I was debugging some code from a vendor and had that assumption challenged. The only reason I can think of for this code failing is that the Substring() function is getting called on data that should have been filtered out by the WHERE clause. But it appears that the substring call is being applied before the filtering happens, the query is failing.
Here is an example of what I mean. Let's say we have two tables, each with 2 columns and having 2 rows and 1 row respectively. The first column in each is just an id. NAME is just a string, and NAME_LENGTH tells us how many characters in the name with the same ID. Note that only names with more than one character have a corresponding row in the LONG_NAMES table.
NAMES: ID, NAME
1, "Peter"
2, "X"
LONG_NAMES: ID, NAME_LENGTH
1, 5
If I want a query to print each name with the last 3 letters cut off, I might first try something like this (assuming SQL Server syntax for now):
SELECT substring(NAME,1,len(NAME)-3)
FROM NAMES;
I would soon find out that this would give me an error, because when it reaches "X" it will try using a negative number for in the substring call, and it will fail.
The way my vendor decided to solve this was by filtering out rows where the strings were too short for the len - 3 query to work. He did it by joining to another table:
SELECT substring(NAMES.NAME,1,len(NAMES.NAME)-3)
FROM NAMES
INNER JOIN LONG_NAMES
ON NAMES.ID = LONG_NAMES.ID;
At first glance, this query looks like it might work. The join condition will eliminate any rows that have NAME fields short enough for the substring call to fail.
However, from what I can observe, SQL Server will sometimes try to calculate the the substring expression for everything in the table, and then apply the join to filter out rows. Is this supposed to happen this way? Is there a documented order of operations where I can find out when certain things will happen? Is it specific to a particular Database engine or part of the SQL standard? If I decided to include some predicate on my NAMES table to filter out short names, (like len(NAME) > 3), could SQL Server also choose to apply that after trying to apply the substring? If so then it seems the only safe way to do a substring would be to wrap it in a "case when" construct in the select?
Martin gave this link that pretty much explains what is going on - the query optimizer has free rein to reorder things however it likes. I am including this as an answer so I can accept something. Martin, if you create an answer with your link in it i will gladly accept that instead of this one.
I do want to leave my question here because I think it is a tricky one to search for, and my particular phrasing of the issue may be easier for someone else to find in the future.
TSQL divide by zero encountered despite no columns containing 0
EDIT: As more responses have come in, I am again confused. It does not seem clear yet when exactly the optimizer is allowed to evaluate things in the select clause. I guess I'll have to go find the SQL standard myself and see if i can make sense of it.
Joe Celko, who helped write early SQL standards, has posted something similar to this several times in various USENET newsfroups. (I'm skipping over the clauses that don't apply to your SELECT statement.) He usually said something like "This is how statements are supposed to act like they work". In other words, SQL implementations should behave exactly as if they did these steps, without actually being required to do each of these steps.
Build a working table from all of
the table constructors in the FROM
clause.
Remove from the working table those
rows that do not satisfy the WHERE
clause.
Construct the expressions in the
SELECT clause against the working table.
So, following this, no SQL dbms should act like it evaluates functions in the SELECT clause before it acts like it applies the WHERE clause.
In a recent posting, Joe expands the steps to include CTEs.
CJ Date and Hugh Darwen say essentially the same thing in chapter 11 ("Table Expressions") of their book A Guide to the SQL Standard. They also note that this chapter corresponds to the "Query Specification" section (sections?) in the SQL standards.
You are thinking about something called query execution plan. It's based on query optimization rules, indexes, temporaty buffers and execution time statistics. If you are using SQL Managment Studio you have toolbox over your query editor where you can look at estimated execution plan, it shows how your query will change to gain some speed. So if just used your Name table and it is in buffer, engine might first try to subquery your data, and then join it with other table.