October 28, 2005 at 11:21 am
hi! me again!
As some of you have seen, i've been trying to make some functions to split a delimited value ( ids delimited by ; ) into their description, from a join at another table.
Now that the functions are all working ( split(), id2description(), I tried to put that function inside the main query which makes four or five joins. Fine.
The query works, returns 132 rows in some seconds.
But when I put the function id2description( fielddelimited ) to the main query, it simply keeps runing forever and never ends. I waited for 11 minutes and It was still running
Then I limited main query to 5 rows, 10 rows, 15 rows. Worked with the function included. But when I put more, like 20 rows ( top 20 ), It start to run forever.
How can I find where it is starting to get lost in the query?
Do I have to open close the database conection in the function or something?
I have no clue. Who's fault? The left joins'? the function's join for each row? ( its like 3 or 4 ids mostly for each row )
any idea?
tables structures:
maintable {id, fields, delimitedfield,fk,fk,fk,fk and left joins for those fks} >> results 132 rows
roles (id, description) >> results around 10 rows
delimitedfield = id;id;id;
( the function just split this value, get each id description and return a descr-descr-descr string )
[]s
October 28, 2005 at 2:52 pm
First things first:
1. Functions force row-by-row processing (use them sparingly)
2. Make sure you have indexes in place that are being used by your where clauses, joins, group bys and order bys. (Check Execution plan)
3. We need to see the query or it will be very difficult to guess
Cheers,
* Noel
October 31, 2005 at 5:45 am
these are the functions:
/*
Split()quebrar uma string com valores delimitados por 1 caractere
@param inputstring delimitada
@param delimiterdelimitador com 1 caractere qualquer
@return outputtable output{valor}
@usageSELECT valor FROM Split( 'aa;bb;ff;xx;', '|' )
*/
ALTER FUNCTION Split( @input VARCHAR(1000), @delimiter CHAR(1) = '|' )
RETURNS @output TABLE( valor VARCHAR(1000) )
AS
BEGIN
DECLARE @join VARCHAR(1000)
DECLARE @result VARCHAR(1000)
DECLARE @valor VARCHAR(1000)
WHILE( 1 = 1 )
BEGIN
--ver se o delimitador existe na string
IF charindex( @delimiter, @input ) = 0
BEGIN
--se não existir o delimitador, insere somente a string na tabela de saída
IF( @input '' )
BEGIN
INSERT INTO @output ( valor ) VALUES ( @input )
END
BREAK
END
ELSE
BEGIN
if charindex( ';', @input ) = 1
begin
SET @input = substring( @input, 2, len(@input) )
end
SET @valor = substring( @input, 1, charindex( @delimiter, @input ) -1 )
IF( @valor '' )
BEGIN
INSERT INTO @output ( valor ) VALUES( @valor )
SET @input = SUBSTRING( @input, CHARINDEX( @delimiter, @input )+ 1, LEN( @input ) )
END
END
END
RETURN
END
-- SELECT TOP 10 valor FROM dbo.Split( ';14;0;-1;-2;', ';' )
-- SELECT TOP 10 valor FROM dbo.Split( ';0;', ';' )
/*
ids2Rolename()converte uma tabela de ids (roles.roleid) em suas descrições delimitada por '-'
@param idliststring delimitada
@param delimiterdelimitador com 1 caractere qualquer
@return resultstring
@usageSELECT Split( 'aa;bb;ff;xx;', '|' )
*/
drop function ids2Rolenames
create FUNCTION ids2Rolenames( @idlist VARCHAR(1000), @delimiter CHAR(1) )
RETURNS VARCHAR(1000)
AS
BEGIN
DECLARE @tmp_ids TABLE( valor VARCHAR(1000) )
DECLARE @tmp_distinct TABLE( valor VARCHAR(1000), description VARCHAR(1000) )
DECLARE @tmp_description TABLE( description VARCHAR(1000) )
DECLARE @result VARCHAR(1000)
/* get a table with splited data - each id in a row */
INSERT INTO @tmp_ids SELECT valor FROM Split(@idlist, @delimiter )
INSERT INTO @tmp_distinct
SELECT
s.valor ,
CASE s.valor
WHEN '0' THEN 'Administrators'
WHEN '-1' THEN 'All Users'
WHEN '-2' THEN 'Host'
WHEN '-3' THEN 'Unauthenticated Users'
WHEN '' THEN ''
WHEN NULL THEN ''
ELSE r.rolename
END AS description
FROM @tmp_ids s
LEFT OUTER JOIN roles r ON s.valor = r.roleid
INSERT INTO @tmp_description SELECT DISTINCT(description) FROM @tmp_distinct
SELECT @result = ISNULL( @result + ' - ', '' ) + description FROM @tmp_description
RETURN @result
END
-- select valor from Split( ';0;-1;-2;', ';' )
-- SELECT dbo.ids2Rolenames( '14;0;-1;-2;', ';' ) as rolenames
this is the main query that crashes with more than 10 results:
SELECT TOP 11
p.PortalName AS NomedoPortal,
tp.TabName AS PáginaPai,
t.TabName AS Página,
m.ModuleTitle AS TitulodoModulo,
md.FriendlyName AS NomedoModulo,
m.PaneName AS PanedoMódulo,
m.Alignment AS Alinhamento,
m.AuthorizedEditRoles AS PodemEditar,
m.AuthorizedViewRoles AS PodemVer
--,( SELECT dbo.ids2Rolenames( m.AuthorizedViewRoles, ';' ) ) AS PodemVer_descr
FROM
tabs t
LEFT OUTER JOIN tabs tp ON t.parentid = tp.parentid
LEFT OUTER JOIN portals p ON t.portalid = p.portalid
LEFT OUTER JOIN modules m ON t.tabid = m.tabid
LEFT OUTER JOIN moduledefinitions md ON m.moduledefid = md.moduledefid
LEFT OUTER JOIN desktopmodules dm ON md.desktopmoduleid = dm.desktopmoduleid
WHERE 0=0
AND t.isdeleted = 0
AND m.isdeleted = 0
AND dm.isadmin = 0 --AND m.moduleid = 367
AND p.PortalName IS NOT NULL --modulos internos de banners
ORDER BY m.ModuleTitle
October 31, 2005 at 2:55 pm
If you're not going to need to filter the results of the function, I would apply it in an outer step.
That is: do your primary select statement in an embedded query and apply the function in the outer query.
Select w.*, functioncall( w.listcolumn, ';') as desc_list
FROM ( SELECT....outer join everthingunderthesun...etc.
) w
Then optimize the internal query by itself, and see how it performs stand alone and then with the outer query with the function call.
Viewing 4 posts - 1 through 3 (of 3 total)
You must be logged in to reply to this topic. Login to reply