How to use one param in multiple places in birt report [duplicate] - report

This question already has an answer here:
Birt Report Multiple Parameters for the same field
(1 answer)
Closed 6 years ago.
I want to pass one param in birt report and use it in multiple palces , for example :
SELECT * FROM tab1 WHERE startDAte = trunc(sysdate)
UNION
SELECT *FROM tab1 WHERE startDate= trunc(sysdate-1)
So i want to make sysdate like a variable :
SELECT * FROM tab1 WHERE startDAte = trunc(?)
UNION
SELECT *FROM tab1 WHERE startDate= trunc(?-1)
How can i do that ? Thanks

This has already been answered in Reusing an anonymous parameter in a prepared statement
If your database is Oracle, you can also use the following syntax:
WITH params AS
( select ? as p_date,
? as p_whatever,
...
from dual
)
SELECT tab1.* FROM tab1, params WHERE tab1.startDate = trunc (params.p_date)
UNION
SELECT tab1.* FROM tab1, params WHERE startDate= trunc (parms.p_date - 1)
Note that this does not have a negative performance impact, because the DB is clever enough to detect that the params inline-view contains exactly one row.

Related

How to resolve ORA-01489: result of string concatenation is too long [duplicate]

This question already has an answer here:
Create Pivot view in SQL from a SQL table
(1 answer)
Closed 2 years ago.
I have a table temp and Im trying to query as below :
SELECT
LISTAGG( 'MAX(CASE WHEN CATEGORY = '''||CATEGORY||''' THEN "'||"LEVEL"||'" END) AS "'||
"LEVEL"||'_'||CATEGORY||'"' , ',' ) WITHIN GROUP ( ORDER BY CATEGORY, "LEVEL" DESC
) AS col2
FROM
(
SELECT DISTINCT
"LEVEL",
CATEGORY
FROM
TEMP );
`
I get error as [Code: 1489, SQL State: 72000] ORA-01489: result of string concatenation is too long
Im unable to get rid of this error.
I'm using SQL Commander of DBVisualizer .
I also tried to declare variable before but it does not seem to work:
#ECHO ${col2 ||32767||varchar2}$
I tried to ALTER SYSTEM SET MAX_STRING_SIZE = EXTENDED; which is also giving error : [Code: 2065, SQL State: 42000] ORA-02065: illegal option for ALTER SYSTEM.
Is there anything wrong in the code front if not what could be the workaround for this
If LISTAGG won't work (as, obviously, resulting string is longer than 4000 characters), switch to not-that-elegant XMLAGG which doesn't have that restriction. Result should be the same (compare these two):
SQL> select listagg(dname, ',') within group (order by dname) result
2 from dept;
RESULT
--------------------------------------------------------------------------------
ACCOUNTING,OPERATIONS,RESEARCH,SALES
SQL> select rtrim(xmlagg(xmlelement(e, dname ||',') order by dname).extract
2 ('//text()'), ',') result
3 from dept;
RESULT
--------------------------------------------------------------------------------
ACCOUNTING,OPERATIONS,RESEARCH,SALES
SQL>

Give alias to anonymous column of global collection type in SELECT FROM TABLE(collection)

I'm trying to use values from an apex_t_numbers collection in a SELECT query as WITH subquery:
atn_cur_ids := apex_string.split_numbers(arg_v_ids, ':');
-- So if arg_v_ids := '1:2:3', then atn_cur_ids := apex_t_numbers(1, 2, 3)
with t_cur_ids as (
select * as id from table(atn_cur_ids);
)
select text from t_texts
join t_cur_ids on t_texts.id = t_cur_ids.id
And here's the problem - apex_t_numbers is a table of number, not of record type with named fields. Oracle SQL doesn't allow to give aliases to a * even if it has only one single "anonymous" column.
A possible solution could be a function that both
receives * and
returns value per row
But I am aware of only one that can get a * and return something - count(*), and it doesn't meet the second requirement.
Alright, found a solution. It could be done with column_value as a name of column:
with t_cur_ids as (
select column_value as id from table(atn_cur_ids);
)
select text from t_texts
join t_cur_ids on t_texts.id = t_cur_ids.id

PL/SQL - comma separated list within IN CLAUSE

I am having trouble getting a block of pl/sql code to work. In the top of my procedure I get some data from my oracle apex application on what checkboxes are checked. Because the report that contains the checkboxes is generated dynamically I have to loop through the
APEX_APPLICATION.G_F01
list and generate a comma separated string which looks like this
v_list VARCHAR2(255) := (1,3,5,9,10);
I want to then query on that list later and place the v_list on an IN clause like so
SELECT * FROM users
WHERE user_id IN (v_list);
This of course throws an error. My question is what can I convert the v_list to in order to be able to insert it into a IN clause in a query within a pl/sql procedure?
If users is small and user_id doesn't contain commas, you could use:
SELECT * FROM users WHERE ',' || v_list || ',' LIKE '%,'||user_id||',%'
This query is not optimal though because it can't use indexes on user_id.
I advise you to use a pipelined function that returns a table of NUMBER that you can query directly. For example:
CREATE TYPE tab_number IS TABLE OF NUMBER;
/
CREATE OR REPLACE FUNCTION string_to_table_num(p VARCHAR2)
RETURN tab_number
PIPELINED IS
BEGIN
FOR cc IN (SELECT rtrim(regexp_substr(str, '[^,]*,', 1, level), ',') res
FROM (SELECT p || ',' str FROM dual)
CONNECT BY level <= length(str)
- length(replace(str, ',', ''))) LOOP
PIPE ROW(cc.res);
END LOOP;
END;
/
You would then be able to build queries such as:
SELECT *
FROM users
WHERE user_id IN (SELECT *
FROM TABLE(string_to_table_num('1,2,3,4,5'));
You can use XMLTABLE as follows
SELECT * FROM users
WHERE user_id IN (SELECT to_number(column_value) FROM XMLTABLE(v_list));
I have tried to find a solution for that too but never succeeded. You can build the query as a string and then run EXECUTE IMMEDIATE, see http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/dynamic.htm#i14500.
That said, it just occurred to me that the argument of an IN clause can be a sub-select:
SELECT * FROM users
WHERE user_id IN (SELECT something FROM somewhere)
so, is it possible to expose the checkbox values as a stored function? Then you might be able to do something like
SELECT * FROM users
WHERE user_id IN (SELECT my_package.checkbox_func FROM dual)
Personally, i like this approach:
with t as (select 'a,b,c,d,e' str from dual)
--
select val
from t, xmltable('/root/e/text()'
passing xmltype('<root><e>' || replace(t.str,',','</e><e>')|| '</e></root>')
columns val varchar2(10) path '/'
)
Which can be found among other examples in Thread: Split Comma Delimited String Oracle
If you feel like swamping in even more options, visit the OTN plsql forums.

I need to write a sql query to display top 25 records with a catch

I need to write a query as follows which will be bound to a grid
select top 25 * from ErrTable Order by DateErrorad Desc
However, I need to write this query to return only 25 records at a time, but when a user clicks next it will display the next 25 most recent records from the db.
How could I accomplish this?
You can implement a 'paging' technique using ROW_NUMBER() as detailed in this post: http://www.davidhayden.com/blog/dave/archive/2005/12/30/2652.aspx
Ok, since I don't know what Database Server/engine but basically you will need a range (in your case 25) and a page number (e.g. 0 is first page, 1 for next page of 25 records, etc).
In MySQL, you can do this (using the LIMIT command)....
SELECT * FROM TABLE LIMIT START, RANGE;
Wher TABLE is your table name, START is your start index/range, e.g if you have record 0 - 24, you can set start = 25, to read the next 25 (which is where RANGE comes into play).
This is only available in MySQL, in DB2 it's different though. Find out who your DB server/engine handles pagination.
In DB2:
SELECT * FROM TABLE FETCH FIRST N ROW ONLY;
Where N is a numeric value.
Edit For MSSQL, you can see another related post:
How to implement LIMIT with Microsoft SQL Server?
Here's an article that shows Paging in ASP.NET.
In MySQL you can do that with LIMIT, in MSSQL i don't know if that works.
SELECT * FROM table LIMIT 10
or
SELECT * FROM table LIMIT 0, 10
This will display the first 10 results from the database.
SELECT * FROM table LIMIT 5, 5
This will show records 6 to 10
Assuming you're using SQL Server (based on the ASP.NET tag):
declare #offset int
set #offset = 25
select * from (
select *, row_number() over (order by DateErrorad desc) as i from ErrTable
) a
where i <= #offset + 25 and i > #offset
I would highly recommend you use an ORM, though. I love LINQ-to-SQL (it's a perfect complement to ASP.NET), and with that you could do this as:
var rows = Errors.Skip(offset).Take(25);
You can use the LIMIT command to pick entries in a given range. However, I'm not sure if all engines support it, so a more general solution (albeit less efficient, I reckon), is...
SELECT TOP 25 *
FROM YOURTABLE
WHERE IDCOL NOT IN (SELECT TOP 25 * FROM YOURTABLE)
Sorry for the loose definition, I'm leaving and can't answer in more detail.
I guess it depends on your DBMS, the following LINQ2SQL-query
(table DatabaseLogs from AdventureWorks)
using (DataClasses1DataContext context = new DataClasses1DataContext())
{
context.Log = Console.Out;
var qq3 = context.DatabaseLogs.Skip(20).Take(10).ToList();
}
generates the following query for MSSQL
SELECT [t1].[DatabaseLogID], [t1].[PostTime], [t1].[DatabaseUser], [t1].[Event], [t1].[Schema] AS [Schema], [t1].[Object], [t1].[TSQL], [t1].[XmlEvent]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[DatabaseLogID], [t0].[PostTime], [t0].[DatabaseUser], [t0].[Event], [t0].[Schema], [t0].[Object], [t0].[TSQL]) AS [ROW_NUMBER], [t0].[DatabaseLogID], [t0].[PostTime], [t0].[DatabaseUser], [t0].[Event], [t0].[Schema], [t0].[Object], [t0].[TSQL], [t0].[XmlEvent]
FROM [dbo].[DatabaseLog] AS [t0]
) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN #p0 + 1 AND #p0 + #p1
ORDER BY [t1].[ROW_NUMBER]
-- #p0: Input Int (Size = -1; Prec = 0; Scale = 0) [20]
-- #p1: Input Int (Size = -1; Prec = 0; Scale = 0) [10]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
by creating a stored procedure and passing your range
create procedure dbo.SelectWindow
#start int, #end int
as
begin
select *
from
(
select
*,
row_number() (order by ID) as Row
from dbo.table
) a
where Row between #start and #end
end
go

How do I provide a string with a list of values to an "IN" statement [duplicate]

This question already has answers here:
SQL - Stored Procedure with Select Statement using IN (#Variable_CommaDelimitedListOfIDS)
(7 answers)
Closed 2 years ago.
I am creating a string that is a list of comma-delimitted values by looping through the selections in a CheckBoxList. I am able to display this value, so I know that it is creating what I expect. I am attempting to pass this list to an IN statment in a SELECT query:
SelectCommand="SELECT ThisDate, DATEPART(dw, ThisDate) AS Expr1 FROM fbCalendar WHERE (ThisDate >= #ThisDate) AND (ThisDate <= #ThisDate2) AND (DATEPART(dw, ThisDate) IN (#TheseDays))"
<asp:ControlParameter ControlID="Label1" Name="TheseDays" PropertyName="Text" Type="String" />
This works fine as long as there is only a single item selected, but selecting a second item fails with the message:
Conversion failed when converting the nvarchar value '4,5' to data type int.
However, I do not understand when this would be converted to an INT. I have tried many different formatting attempts (such as encapsulating the string in parenthesis (e.g. "(4,5)" ) for the SELECT query, but I have yet to find the right one to make this work. It seems like formatting is the problem, but perhaps I am missing something else.
Degan.
I created a table to store the values to pass to the query. It just
doesn't seem right.
You don't have to create an actual table. You can use a Table Valued Function and use that in your query e.g. as below.
(DATEPART(dw, ThisDate) IN (SELECT [item] FROM dbo.fnSplit(#TheseDays, ',')))
This uses the TVF from http://www.eggheadcafe.com/community/aspnet/13/10021854/fnsplit.aspx).
CREATE FUNCTION dbo.fnSplit(
#sInputList VARCHAR(8000) -- List of delimited items
, #sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items
) RETURNS #List TABLE (item VARCHAR(8000))
BEGIN
DECLARE #sItem VARCHAR(8000)
WHILE CHARINDEX(#sDelimiter,#sInputList,0) <> 0
BEGIN
SELECT
#sItem=RTRIM(LTRIM(SUBSTRING(#sInputList,1,CHARINDEX(#sDelimiter,#sInputList,0)-1))),
#sInputList=RTRIM(LTRIM(SUBSTRING(#sInputList,CHARINDEX(#sDelimiter,#sInputList,0)+LEN(#sDelimiter),LEN(#sInputList))))
IF LEN(#sItem) > 0
INSERT INTO #List SELECT #sItem
END
IF LEN(#sInputList) > 0
INSERT INTO #List SELECT #sInputList -- Put the last item in
RETURN
END
GO

Resources