Tuesday, March 27, 2012
Getting a custom sized page from a sorted result set
I've tried numerous solutions to this classic problem. I know how to do a
pretty scalable solution, but I'd like to hear some more ideas.
What I do now is something like this:
1. Declare a cursor inside an exec statement since order by doesn't support
variables
(I know about the alternative ORDER BY CASE @.param WHEN 1 THEN [column]
WHEN 2 THEN [column] DESC etc..., but it would need just as much or more
code)
2. Create a temporary table identical to the result set
3. Declare variables for all fields
4. Fetch from cursor [pagesize] times from [start] while inserting into
variables and then temporary table
5. Select from the temp table
6. Return total count of the result set for the pager mechanism
The main challenges I've had is how to fetch the correct page. In SQL Server
2005 I thought my troubles were gone since we got the new TOP(@.parameter)
feature, but when it comes to sorting it's still impossible.
Anyway, the demands are
1. Fast browsing of 5000+ rows big result sets
2. Sorting by any column
3. User defined page size
One alternative I'm considering is use a query returning the entire result
set, and then using a reader instead in .net, but the amount of data fetched
will still be too much when you reach the last page. I'm not sure though if
the sql injection removal code, the exec statement and the cursor will use
just as much resources... Should measure it someday, but if anyone allready
did it, I'd appreciate a link. :P
Anyone got a better solution than the one on top?
(Some MySQL fans I know mock me because they've got LIMIT, I want to hit
back.. ;) )
Lars-ErikIf I understand correctly, you want to retrieve N rows, starting from some
point in the result set.
You can solve part of the problem with set rowcount. You can use variables
so it can be passed to the stored procedure.
for example:
create procedure usp_GetPage
(
@.Number int
)
as
set rowcount @.number
select col1, col2
from table1
-- This will return @.Number rows from the table.
Paging is, offcourse more complicated but perhaps this helps a bit? The rest
is entirely up to the way you want to implement ordering and what would be
the criteria for defining pages (starting point and such)
MC
"Lars-Erik Aabech" <larserik@.newsgroup.nospam> wrote in message
news:eF4a%23UQ5FHA.2864@.tk2msftngp13.phx.gbl...
> Hi!
> I've tried numerous solutions to this classic problem. I know how to do a
> pretty scalable solution, but I'd like to hear some more ideas.
> What I do now is something like this:
> 1. Declare a cursor inside an exec statement since order by doesn't
> support variables
> (I know about the alternative ORDER BY CASE @.param WHEN 1 THEN [column]
> WHEN 2 THEN [column] DESC etc..., but it would need just as much or more
> code)
> 2. Create a temporary table identical to the result set
> 3. Declare variables for all fields
> 4. Fetch from cursor [pagesize] times from [start] while inserting into
> variables and then temporary table
> 5. Select from the temp table
> 6. Return total count of the result set for the pager mechanism
> The main challenges I've had is how to fetch the correct page. In SQL
> Server 2005 I thought my troubles were gone since we got the new
> TOP(@.parameter) feature, but when it comes to sorting it's still
> impossible.
> Anyway, the demands are
> 1. Fast browsing of 5000+ rows big result sets
> 2. Sorting by any column
> 3. User defined page size
> One alternative I'm considering is use a query returning the entire result
> set, and then using a reader instead in .net, but the amount of data
> fetched will still be too much when you reach the last page. I'm not sure
> though if the sql injection removal code, the exec statement and the
> cursor will use just as much resources... Should measure it someday, but
> if anyone allready did it, I'd appreciate a link. :P
> Anyone got a better solution than the one on top?
> (Some MySQL fans I know mock me because they've got LIMIT, I want to hit
> back.. ;) )
> Lars-Erik
>|||http://www.aspfaq.com/show.asp?id=2120
David Portas
SQL Server MVP
--|||Thanks guys :)
Both relevant info! Didn't know about the @.rowcount setting, and the
measures on the faq page was pretty interresting.
L-E
"Lars-Erik Aabech" <larserik@.newsgroup.nospam> wrote in message
news:eF4a%23UQ5FHA.2864@.tk2msftngp13.phx.gbl...
> Hi!
> I've tried numerous solutions to this classic problem. I know how to do a
> pretty scalable solution, but I'd like to hear some more ideas.
> What I do now is something like this:
> 1. Declare a cursor inside an exec statement since order by doesn't
> support variables
> (I know about the alternative ORDER BY CASE @.param WHEN 1 THEN [column]
> WHEN 2 THEN [column] DESC etc..., but it would need just as much or more
> code)
> 2. Create a temporary table identical to the result set
> 3. Declare variables for all fields
> 4. Fetch from cursor [pagesize] times from [start] while inserting into
> variables and then temporary table
> 5. Select from the temp table
> 6. Return total count of the result set for the pager mechanism
> The main challenges I've had is how to fetch the correct page. In SQL
> Server 2005 I thought my troubles were gone since we got the new
> TOP(@.parameter) feature, but when it comes to sorting it's still
> impossible.
> Anyway, the demands are
> 1. Fast browsing of 5000+ rows big result sets
> 2. Sorting by any column
> 3. User defined page size
> One alternative I'm considering is use a query returning the entire result
> set, and then using a reader instead in .net, but the amount of data
> fetched will still be too much when you reach the last page. I'm not sure
> though if the sql injection removal code, the exec statement and the
> cursor will use just as much resources... Should measure it someday, but
> if anyone allready did it, I'd appreciate a link. :P
> Anyone got a better solution than the one on top?
> (Some MySQL fans I know mock me because they've got LIMIT, I want to hit
> back.. ;) )
> Lars-Erik
>
Monday, March 26, 2012
GetReportParameters ignores language="en-gb"?
Hello
I've integrated my reports into an app using the ReportViewer control, and I've created custom parameter selection controls. I want the user to be able to enter dates in dd/mm/yy format into a textbox. I've set the language of my reports to en-gb.
The SetParametes method of the ReportViewer control copes with this fine, but when I pass a date string in dd/mm/yy format into GetReportParameters, I get a 'parameter value not valid for its type' error. But it works for date strings in mm/dd/yy format, so it's as if GetReportParameters is ignoring my language setting.
Has anyone got any idea as to where I'm going wrong?
Thanks in advance
Dominic
After a little more playing around with this I've found that, on my machine, the SetParameters method always wants dates in dd/mm/yy format, whilst the GetReportParameters web method of the Report Service always wants dates in mm/dd/yy format, regardless of what I set the language of the report to.
Does anyone know what's going on?
Friday, March 9, 2012
Get the list of variables in a package inside a custom component
Hi
I am developing custom dataflow component ,I need to get the of variables of the current package in the component , how can i get it?
Thanks
Mani
Why do you need a list of variables?
Normally the two things you would do in a component is to validate a variable exists and read or write the value. Both of these can be achieved with the VariableDispenser class that is avilable from the base PipelineComponent object.
For example, in validate I would do something like this-
object obj1 = ComponentHelper.GetPropertyValue("OutputRowCountVariable", base.ComponentMetaData());
if ((obj1 != null) && (obj1.ToString().Length > 0))
{
if (!base.VariableDispenser().Contains(obj1.ToString()))
{
this.PostError(string.Format(Resources.ErrorPropertyInvalidVariableNotExist, "OutputRowCountVariable", obj1.ToString()));
return 1;
}
if (!this.ValidateVariableType(obj1.ToString(), out code1))
{
this.PostError(string.Format(Resources.ErrorInvalidVariableType, "OutputRowCountVariable", code1.ToString()));
return 1;
}
}
|||
Hi Darren
I am developing a oracle source component , I need to get the table or view name which are stored as variables. Iam not getting the ComponentHelper class .
thanks
Mani
|||So you do not need a list of variables, you just need to get the variable value. Use the VariableDispenser. Ignore the ComponenHelper, that is just a wrapper of mine, and in that instance I am just getting the value, nothing more than that.|||hi thanks darren i got it i used the code
IDTSVariables90 var;
ArrayList tableOrViewName = new ArrayList();
this.VariableDispenser.LockForRead("TableName");
this.VariableDispenser.GetVariables(out var);
foreach (IDTSVariable90 variable in var)
{
tableOrViewName.Add(variable.Value);
}
Thanks
Mani
|||A minor point but you could save the loop and array. You are only reading from one variable, so you could use LockOneForRead, e.g.
string tableName = "";
IDTSVariables90 variables = null;
VariableDispenser.LockOneForRead("TableName", ref variables);
tableName = variable.Value.ToString();
variables.Unlock()
You should probably check that the Value of teh variable is not null as well, before calling ToString. Always call Unlock as soon as you can.
If you expect multiple tables to be selected, then this would need to be a delmited list in your variable value, you cannot have multiple variables of the same name. You could have a more complex type for the variable value, but I would use a delimited string so it is easier to manage for both design-time setting and also persistance. You can set a string through an expression for example, but not an object.
Sunday, February 26, 2012
Get results from a custom formula
ADCode ADAmount
-
GIS 100
DPF 150
DPF.ADV 200
HRA 100
I want to give the user a capability to create any formula using column values and there by create a new ADCode depending upon other ADCodes, example:
New_ADCode_1 = (GIS + DPF + DPF.ADV)/20 * 100
New_ADCode_2 = 3 * (HRA)
Any idea on how to substitute values in the formula of the ADCodes that are present and create a new ADCode that uses this formula every time an employees pay is calculated.
I am using SQL Server 2005 with C#.How many ADCode do you have? If not many. You can simply SELECT them out through ADO.NET, cache them through Dictionary datastructure in C#. And use them whenever you want.
Because for formula caculation, .NET is much powerful than T-SQL.
Hope it'll be helpful.
|||
Here it is,
Code Snippet
Create Table data (
[Empid] int ,
[ADCode] Varchar(100) ,
[ADAmount] int
);
Insert Into data Values('1','GIS','100');
Insert Into data Values('1','DPF','150');
Insert Into data Values('1','DPF.ADV','200');
Insert Into data Values('1','HRA','100');
Insert Into data Values('2','GIS','100');
Insert Into data Values('2','DPF','150');
Insert Into data Values('2','DPF.ADV','200');
Insert Into data Values('2','HRA','100');
Approach 1:
Code Snippet
create function formula1(@.Empid int)
returns float
as
Begin
Declare @.result as float;
Select @.result = cast(Sum(AdAmount) as float)/20.0 * 100.0
From
data
Where
Adcode in('GIS','DPF','DPF.ADV')
and Empid = @.Empid;
return @.result;
End
create function formula2(@.Empid int)
returns float
as
Begin
Declare @.result as float;
Select @.result = 3 *AdAmount
From
data
Where
Adcode = 'HRA'
and Empid = @.Empid;
return @.result;
End
select *, dbo.formula1(empid), dbo.formula2(empid) from data
Approach 2:
Code Snippet
create function FormulaResults(@.Empid int)
returns table
as
Return
(
Select formula1 = cast(Sum(case when Adcode in('GIS','DPF','DPF.ADV') Then AdAmount End) as float)/20.0 * 100.0,
formula2 = cast(Sum(case when Adcode = ('HRA') Then AdAmount End) as float) * 3
From
data
Where
Empid = @.Empid
)
select *, formula1, formula2 from data d CROSS APPLYFormulaResults(d.empid) f
|||Manivannan,Thanks for the solution. It seems a good one.
As you might be knowing, any Payroll system has Allowances and Deductions. Some Allowances and Deductions are applied directly, i.e., either they are added to Basic Pay or subtracted from Gross Pay. Some Allowances/Deductions have a special formula.
I want to know whether all calculations must reside as stored procedures/functions or they can be written entirely in a DLL.
|||
Frankly speaking about the application design, it is not good practice to overload your database with business logics, the new programming languages are much easier to create these functional requirements and rules. It is much easier to maintain also.