Oracle 11g Concat function error - sql

I'm encountering this error:
ORA-00904: "LASTNAME": invalid identifier
When trying to make a report using concat function.
Here is the query:
SELECT 'Full Name','User Name', 'Email' FROM Dual
UNION ALL
SELECT distinct concat(concat(firstname, ' '), lastname), username, Email
FROM
(
select distinct concat(concat(firstname, ' '), lastname), username, Email
from sas_aclentry, sas_usergroup
where sas_aclentry.userkey = sas_usergroup.userkey
and objecttype in (16,3,4,101,14,102) and productkey = 1 and type = 1 and privilege !=0 and isdeleted = 0 and STATUS IN (0, 32)
UNION
select distinct concat(concat(firstname, ' '), lastname), username, Email
from sas_objecttree
join sas_usergroup on sas_usergroup.userkey = sas_objecttree.childkey
where isdeleted = 0 and STATUS IN (0, 32)
and parentkey in (
select distinct sas_aclentry.userkey
from sas_aclentry
join sas_usergroup on sas_usergroup.userkey = sas_aclentry.userkey
where objecttype in (16,3,4,101,14,102) and productkey = 1 and type = 2 and privilege !=0 and isdeleted = 0)
)
WHERE UPPER(Email) LIKE '%SAS%';
Wandered on google but could not find any way to make this works.
Please help.
Appreciate any input.
Will

The error seems to be that your outer query tries to select lastname from the derived table, which does not expose any column with that name. I'm guessing you meant to alias the concated column in the derived table and select that.
Try changing the beginning of the query to this:
SELECT 'Full Name','User Name', 'Email' FROM Dual
UNION ALL
SELECT fullname, username, Email
FROM
(
select distinct firstname || ' ' || lastname as fullname, username, Email
With some databases concat can take more than two arguments, I'm not sure this is true for Oracle though, but you should be able to use the concatenation operator || and change your nested concat functions to this:
firstname || ' ' || lastname as fullname
which makes the code a bit cleaner. (I would also try to be consistent in the use of explicit joins - in the derived table you use implicit joins for the first query and explicit for the second).

There are many mistakes in this query, besides what has already been pointed out (you are selecting "lastname" from a subquery whose projection does not contain a column by that name).
When you do a UNION, the first term of the union must have column names or aliases, which will be used for all the terms of the union. It does not suffice to select three strings from dual (which are probably meant to be used as headers), you must also give each of them an alias. For example, select 'Full Name' as fullname, ... from dual. Alternatively, you may leave the select... from dual for later in the union.
The fact that the "column headers" are shown at the top of the query does not mean they will be at the top of the result set. If you want them to show up at the top of your results, you must use an ORDER BY clause (which probably also means you will need to be able to order by something).
In the "problem" part of the Union, the select with a subquery, with the names and concatenations, you concatenate in the subquery, and then in the select list of the outer query you concatenate again (and supposedly the same three columns that the subquery concatenated already). This will not produce the result you wanted even if there were no syntax errors. What you probably want to do is to do the concatenation in the subquery (and best to use the || operator which may be used repeatedly, instead of concat() which is limited in Oracle); alias the result of the concatenation as fullname, and select fullname in the outer query.
After you fix these issues, others may come to the front; I (we) am/are not able to test, since you didn't provide any test inputs. Please follow up / write back if you need more help. Good luck!

Related

Using subquery with IN clause

I am stuck at one particular problem here, I am fetching ID's from one column that are like this ',90132988,90133148,72964884,' Let's say this value is stored in a column ColumnA of Table1.
I want to use this in another query that's using IN clause something like this.
SELECT *
FROM USER_GROUP
WHERE ID IN (SELECT CONCAT(CONCAT('(',REPLACE(LTRIM(RTRIM(REPLACE(COLUMNA, ',', ' '))), ' ', ',')),')') FROM Table1)
When I run this query I get invalid number error. Any suggestions ?
You get a number error because id is a number. So, Oracle wisely assumes that the subquery returns numbers.
I think the logic you want is:
SELECT ug.*
FROM USER_GROUP ug
WHERE EXISTS (SELECT 1
FROM Table1 t1
WHERE t1.COLUMNA LIKE '%,' || ug.ID || ',%'
);
I strongly discourage you from storing number lists as strings. Just store one row per number. That is really much simpler and the resulting code will be more efficient.
You can try converting "ID" using TO_CHAR, but you will lose the use of any index on ID if you have one.
SELECT *
FROM USER_GROUP
WHERE TO_CHAR(ID) IN (SELECT CONCAT(CONCAT('(',REPLACE(LTRIM(RTRIM(REPLACE(COLUMNA, ',', ' '))), ' ', ',')),')') FROM Table1)

Concatenating strings in PostgreSQL result

I have an SQL query like this:
SELECT DISTINCT(id) FROM users WHERE ...
and I would like to display the results like that:
user=12355
user=78949
user=9898
user=489891
Basically with "user=" prepended. Is it possible to do this with PostgreSQL? I've tried with STRING_AGG('user=', DISTINCT(id)) but got an error on DISTINCT(id). Any idea?
I'd use a plain GROUP BY for this.
SELECT format('user=%s',id)
FROM users
GROUP BY id;
http://sqlfiddle.com/#!1/39727/3
This will be considerably more efficient than using DISTINCT on the string concatenation.
You should be able to use || for string concatenation:
SELECT DISTINCT('user=' || id)
FROM users
WHERE ...
SQL Fiddle Demo
This might be useful as well:
http://www.postgresql.org/docs/current/static/functions-string.html
The only reason you got an error message from string_agg() is because you forgot the second parameter which is required. This very simple query would just work:
SELECT string_agg('user=' || id, E'\n')
FROM users
WHERE ...
E'\n' .. newline character
Produces one row with the exactly the string you have in your question.
You do not need either DISTINCT or GROUP BY unless you have duplicates in id - in which case you'd need a subquery:
SELECT string_agg('user=' || id, E'\n')
FROM (SELECT id FROM users GROUP BY id) x
Simply
Select concat('user=',id) from users

Wildcards in sql

How does wildcards works in sql. If I do select * from table it give all the fields. But if I do select a* from table it gives error. Shouldn't it give all fields which begins with a?
I am little confused.
SELECT * FROM tableName literally means "select all columns from tableName".
Philip Graham is right about his answer where he asked to use a.*
Wildcards help you search for strings about which you are not sure. These are almost always used with the LIKE keyword and put in WHERE clauses or searched CASE statements.
There are two wildcard characters - % and _.
% is used to find any string of 0 or more length.
E.g.,
SELECT firstName
FROM persons
WHERE UPPER(firstName) LIKE 'J%'
This will return all the firstName from the persons table where firstname starts with letter J. This would return "Jason", "James", "Josh", "Jessica" and much more.
Note that UPPER function was used to eliminate case sensitivity.
Next, you can have an _ character that looks for the presence of one single character.
SELECT firstName
FROM persons
WHERE UPPER(firstName) LIKE 'J_M__'
This would return "James", "Jimmy", "Jamos", "Jxmx" and filter away any "Jason", "Jaguar", etc.
For more info click here
You can use a.* where a is the name of the table. For instance in
select a.* from a left join b on a.id = b.id
You would return only the fields from a but not from b
If want to use a wild card in SQL, You need to key on the column that you want to filter using LIKE.
SELECT *
FROM table
WHERE column_name LIKE 'a%';
This will give you everything that begins with 'a' on that column.
If you don't want all the columns, you must explicitly give the name of each column that you want in the query.
SELECT LastName, FirstName, Address
FROM table
So if you want all the fields that begin with 'a' you must name all the fields that begin with 'a' in the SELECT statement.
Hope this helps.

Completing a given SQL statement so that another column is displayed in the end

I'm given the following statement:
SELECT id FROM record_database WHERE id = <up to me to complete the statement>
The record database has different fields, among which are id and name.
I'm supposed to complete this select statement so that it displays all the ids and all the corresponding names side by side, and this should be done using this one line of SQL code. A hint was given that UNION or OR can be used.
I tried variations of the following:
SELECT id FROM record_database WHERE id = '*'
UNION
SELECT name FROM record_database WHERE name = '*';
But none of these worked. I tried doing this with AND, tried using display columns, but those didn't work either.
Any help would be appreciated.
This smells a great deal like homework, so I won't offer a complete answer, but you can't just union queries that return dissimilar result sets. I'm inferring that ID is an integer while NAME is some varchar, which won't union as you've listed in your hint.
When you say "complete," are you restricted to adding things to the end? If so, its a non-starter. You can't increase the list of fields being returned merely by adding things to the "WHERE" clause. You need to add things to the actual field list to get them to be returned, so you might clarify whether you are truly restricted to appending to the query you;ve given.
If you are looking for:
id
name
id next
name next
Then use this trick:
SELECT col2
FROM (
SELECT id, col2=convert ( varchar (size of name field),id)
FROM table
WHERE ....
UNION ALL
SELECT id, name
FROM table
WHERE ....
)
ORDER BY id
This order by will bring id and name side by side and col2 will contain id in first row and name in second row.
Cheating. Make the select return 0 rows and add another one that will show 2 columns. All in one and the same line:
SELECT id FROM record_database WHERE id = NULL;SELECT id,name FROM record_database;
No more time should be wasted on silly problems like this.
If both id and name are char (or varchar), you could also do this, concatting the two columns into one:
SELECT id FROM record_database WHERE id = NULL
UNION ALL
SELECT id || '--' || name FROM record_database ;
The id || '--' || name part differs from one DBMS to another. In some, the + is the concat operator, in others there are special functions. So you may need to use:
id + '--' + name
or:
CONCAT(id, '--', name)
Try this
SELECT * FROM record_database WHERE id = '*' OR name = '*'

Use sql to select data, then insert row in first position of result set only (not update database)

If I select a column in a table, say 10 rows, can I use SQL to insert a 'please select' row into the first position using SQL only? I want to insert it in the result set only - not the database.
First you should know this is a bad idea.
You are confusing your presentation layer and your database layer. Forcing SQL to do things like output status messages or feedback to users is an antipattern to be avoided.
That being said, if the column is of a string type (char, varchar, etc), you can do something like:
SELECT 'Please Select'
UNION ALL
SELECT TOP 10 Varcharfield
FROM Mytable
If it's numeric then no unless you cast it to a string type.
Here's something you can try:
SELECT u.YourVarcharColumnName
FROM (
SELECT 1 AS rID, 'Please select' AS YourVarcharColumnName
UNION
SELECT 2 AS rID, YourVarcharColumnName
FROM YourTableName
) u
ORDER BY u.rID;
I placed rID in place and sorted by it as an extreme-case-measure when your intended first rowset does not come out on top...
However, you should keep in mind that YourVarcharColumnName should be (as it says) a string. You'll have to convert it to a string if it's a non-string column.
As #JNK mentioned it.. I thought I should edit my post as well:
Please first try:
SELECT 'Please select' AS YourVarcharColumnName
UNION
SELECT YourVarcharColumnName
FROM YourTableName
Which is similar to what the others have posted. If you ever experience what I've been unfortunate to encounter and 'Please select' doesn't come out on top, please refer to the query I posted at the top.. Thanks!
SELECT '(Please select)'
UNION
SELECT ColumnName FROM TableName