How can i limit the output of select statement for a varchar column in Oracle? - oracle

i have a table in which i store the information (product id and description ) of all my products, description column is of type VarChar2(200). i want to format the output of this column in select statement to only result me specific part of output string. E.G Here is my simple select statement:
Select PRODUCTId, PRODUCT_DESC From ProductTable Order By PRODUCTId Desc;
this statement result me the output as:
ProductId Product_Desc
1 Oxford English-Oxford-Oxford Press-Textbook
now i want only the specific part of the output result from product_description column. i have already checked Trim() function but that did not helped me. can someone help me?

A substring function may help.
SELECT SUBSTR('ABCDEFG',3,4) "Substring"
FROM DUAL;

You can use SUBSTR() function. You can provide start and end position for the product_desc column.
The query should be like:
Select product_id,substr(product_desc,2,4) from producttable;
Here you'll get 4 chars from the second one.

Related

Formatting query result

Let's say I have one query that returns column1, column2. I'd like to be able to format the result to a desirable output in Oracle.
I want to mess up with strings that's why I'm asking that question ~~.
create table taTest(
column1 varchar(50),
column2 varchar(50)
)
this is the basic query that I want to format the result from :
select distinct(column1),column2 from taTest;
desired output(for each query result) : column1value(column2value)
I've tried something like this :
select wm_concat(distinct(column1)||'('||column2||')') as result from taTest;
But it seems like I'm not using wm_concat the right way.
Thanks for any input you might provide.
This distinct(column1), column2 is one of the biggest fallacies that I've seen. Because this is same as
select distinct column1, column2. . .
Hence, all you need is this
select
column1 || '('|| column2 || ')' as result
from
taTest
group by
column1, column2;
In this case group by and distinct perform same function
Going back to distinct(column1) - this is false function. The rule of SQL parsing is that anything within ( ) considered a single word\group. Hence (column1) is separated from distinct using () vs empty space -same thing. You can do
select distinct (column1), (column2) . . -- same thing

How to order by field mixed with string and number in Oracle?

These are the field (crane_no) values to be sorted
QC11QC10QC9
I tried the following query:
select * from table order by crane_no DESC
but query results does not give in an order because the field is mixed with staring and number (Example:QC12).
I get following results for above query:
QC9QC11QC10
I want the results to be in order (QC9, QC10, QC11). Thanks
If the data isn't huge, I'd use a regex order by clause:
select
cran_no
from your_table
order by
regexp_substr(cran_no, '^\D*') nulls first,
to_number(regexp_substr(cran_no, '\d+'))
This looks for the numbers in the string, so rows like 'QCC20', 'DCDS90' are ordered properly; it also takes care of nulls.
One approach is to extract the numeric portion of the crane_no columns using SUBSTR(), cast to an integer, and order descending by this value.
SELECT *
FROM yourTable
ORDER BY CAST(SUBSTR(crane_no, 3) AS INT) DESC
Note that I assume in my answer that every entry in crane_no is prefixed with the fixed width QC. If not, then we would have to do more work to identify the numerical component.
select ...
order by to_number( substr( crane_no,3 )) desc

Compare date to month-year in Postgres/Ruby

I have a date column in my table and I would like to 'filter'/select out items after a certain year-month. So if I have data from 2010 on, I have a user input that specifies '2011-10' as the 'earliest date' they want to see data from.
My current SQL looks like this:
select round(sum(amount), 2) as amount,
date_part('month', date) as month
from receipts join items
on receipts.item = items.item
where items.expense = ?
and date_part('year', date)>=2014
and funding = 'General'
group by items.expense, month, items.order
order by items.order desc;
In the second part of the 'where', instead of doing year >= 2014, I want to do something like to_char(date, 'YY-MMMM') >= ? as another parameter and then pass in '2011-10'. However, when I do this:
costsSql = "select round(sum(amount), 2) as amount,
to_char(date, 'YY-MMMM') as year_month
from receipts join items
on receipts.item = items.item
where items.expense = ?
and year_month >= ?
and funding = 'General'
group by items.expense, year_month, items.order
order by items.order desc"
and call that with my two params, I get a postgres error: PG::UndefinedColumn: ERROR: column "year_month" does not exist.
Edit: I converted my YYYY-MM string into a date and passed that in as my param instead and it's working. But I still don't understand why I get the 'column does not exist' error after I created that column in the select clause - can someone explain? Can columns created like that not be used in where clauses?
This error: column "year_month" does not exist happens because year_month is an alias defined the SELECT-list and such aliases can't be refered to in the WHERE clause.
This is based on the fact that the SELECT-list is evaluated after the WHERE clause, see for example: Column alias in where clause? for an explanation from PG developers.
Some databases allow it nonetheless, others don't, and PostgreSQL doesn't. It's one of the many portability hazards between SQL engines.
In the case of the query shown in the question, you don't even need the to_char in the WHERE clause anyway, because as mentioned in the first comment, a direct comparison with a date is simpler and more efficient too.
When a query has a complex expression in the SELECT-list and repeating it in the WHERE clause looks wrong, sometimes it might be refactored to move the expression into a sub-select or a WITH clause at the beginning of the query.

pl-sql include column names in query

A weird request maybe but. My boss wants me to create an admin version of a page we have that displays data from an oracle query in a table.
The admin page, instead of displaying the data (query returns 1 row), needs to return the table name and column name
Ex: Instead of:
Name Initial
==================
Bob A
I want:
Name Initial
============================
Users.FirstName Users.MiddleInitial
I realize I can do this in code but would rather just modify the query to return the data I want so I can leave the report generation code mostly alone.
I don't want to do it in a stored procedure.
So when I spit out the data in the report using something like:
blah blah = MyDataRow("FirstName")
I can leave that as is but instead of it displaying "BOB" it would display "Users.FirstName"
And I want to do the query using select * if possible instead of listing all the columns
So for each of the columns I am querying in the * , I want to get (instead of the column value) the tablename.ColumnName or tablename|columnName
hope you are following- I am confusing myself...
pseudo:
select tablename + '.' + Columnname as WhateverTheColumnNameIs
from Table1
left join Table2 on whatever...
Join Table_Names on blah blah
Whew- after writing all this I think I will just do it on the code side.
But if you are up for it maybe a fun challenge
Oracle does not provide an authentic way(there is no pseudocolumn) to get the column name of a table as a result of a query against that table. But you might consider these two approaches:
Extract column name from an xmltype, formed by passing cursor expression(your query) in the xmltable() function:
-- your table
with t1(first_name, middle_name) as(
select 1,2 from dual
), -- your query
t2 as(
select * -- col1 as "t1.col1"
--, col2 as "t1.col2"
--, col3 as "t1.col3"
from hr.t1
)
select *
from ( select q.object_value.getrootelement() as col_name
, rownum as rn
from xmltable('//*'
passing xmltype(cursor(select * from t2 where rownum = 1))
) q
where q.object_value.getrootelement() not in ('ROWSET', 'ROW')
)
pivot(
max(col_name) for rn in (1 as "name", 2 as "initial")
)
Result:
name initial
--------------- ---------------
FIRST_NAME MIDDLE_NAME
Note: In order for column names to be prefixed with table name, you need to list them
explicitly in the select list of a query and supply an alias, manually.
PL/SQL approach. Starting from Oracle 11g you could use dbms_sql() package and describe_columns() procedure specifically to get the name of columns in the cursor(your select).
This might be what you are looking for, try selecting from system views USER_TAB_COLS or ALL_TAB_COLS.

oracle truncates the value after saving an id with precisions?

I have a table. it has a column with datatype NUMBER(38,20). it is an id column. out application generates the id. i am trying to insert record with an id value of 105.00010. but it inserts only 105.0001. May i know the reason why it is truncating one value(0). it porperly inserts records from 105.00001 to 105.00009. while inserting 105.00010 it is truncating. Please help me.
column size is **NUMBER(38,20)**
Thanks!
See the following test case:
WITH data_values
AS (SELECT 105.0001 AS test_val FROM dual
UNION ALL
SELECT 105.00010 AS test_val FROM dual)
SELECT test_val,
TO_NUMBER(test_val, '999.99999') AS NUM,
TO_CHAR(test_val, '999.99999') AS STR
FROM data_values;
Results in:
TEST_VAL NUM STR
105.0001 105.0001 105.00010
105.0001 105.0001 105.00010
The value after the final non zero digit is irrelevent to Oracle. Both your numbers are equivalent.
The rightmost zeros after the decimal are insignificant, so the value is not truncated, it is still the same value.
If you need it to stay the same you may need to treat the value as a varchar2.

Resources