A sql query where results need to factor in a comma delimited field.

Soldato
Joined
8 Mar 2005
Posts
3,676
Location
London, UK
OK so I have 2 tables:

Table 1:
tbl_Datastore
Datastore_Name | ESX_Hosts
DS1 | ESX_1,ESX_2
DS2 | ESX_2,ESX_3

Table 2:
tbl_ESXHost
ESX_Host | Another_Field
ESX_1 | foo1
ESX_2 | foo2
ESX_3 | foo3

I want to run a query which will result in a row of data for each ESX_Host per each individual Datastore that is presented:

The following query works but its horrendously slow!

Select tbl_ESXHost.ESX_Host, tbl_ESXHost.Another_Field, tbl_Datastore.Datastore_Name FROM tbl_Datastore CROSS JOIN tbl_ESXHost WHERE (tbl_Datastore.ESX_Hosts like '%' + tbl_ESXHost.ESX_Host + '%')

Help! Thanks in advance!
 
Associate
Joined
16 Jan 2003
Posts
1,913
delimited fields are the spawn of the devil.
It will run like a dog as you are producing a Cartesian (CROSS JOIN) and you have a double wildcard for your where clause.

How often do you want to run the SQL and how large are the tables, are the columns you mentioned the only ones on each of the table?
Could you change what populates it?, perhaps you could parse on insert/update so have a table with ESX_Host and DataStore_Name?
 
Soldato
OP
Joined
8 Mar 2005
Posts
3,676
Location
London, UK
tbl_Datastore contains probably a thousand rows of data and tbl_ESXHost less than 200, but tbl_Datastore.ESX_Hosts can contain up to 10 ESX hosts. However even with these low numbers its pitiful. I originally wanted to run the query hourly along with several others but in all honesty I could probably get away with running it once a day and yes there are other columns of data contained on both tables I would want.

Question is with creating a table with that link and insert from each, how do you still reference the comma delimited field? The data within the tables is generated using RVTools, which I do not have any direct control over.
 
Associate
Joined
16 Jan 2003
Posts
1,913
With that sort of row count it shouldn't be that slow. How long does it actually take to run?
Do you know the actual table size?
If you want to export the tables to csv or some example data and upload I'll have a proper look with the same data.

How many of the columns are you interested in compared to how many are on the table. It might be worth looking at adding a covering index for tbl_Datastore. This will mean that the double wildcard will scan less data.

Regarding parsing the data you could try the following. You will need a numbers table for this if you don't already have one.
Code:
create table #tbl_Datastore
(
Datastore_Name VARCHAR(50) NOT NULL,
ESX_Hosts VARCHAR(50) NOT NULL,
)
INSERT INTO #tbl_Datastore VALUES ('DS1', 'ESX_1,ESX_2')
INSERT INTO #tbl_Datastore VALUES ('DS2', 'ESX_2,ESX_3')

CREATE TABLE #tbl_ESXHost
(
ESX_Host VARCHAR(50) NOT NULL,
Another_Field VARCHAR(50) NOT NULL,
)
INSERT INTO #tbl_ESXHost VALUES('ESX_1', 'foo1')
INSERT INTO #tbl_ESXHost VALUES('ESX_2', 'foo2')
INSERT INTO #tbl_ESXHost VALUES('ESX_3', 'foo3')

--Your SQL
SELECT tbl_ESXHost.ESX_Host, tbl_ESXHost.Another_Field, tbl_Datastore.Datastore_Name 
FROM #tbl_Datastore tbl_Datastore
CROSS JOIN #tbl_ESXHost tbl_ESXHost WHERE (tbl_Datastore.ESX_Hosts like '%' + tbl_ESXHost.ESX_Host + '%')

--Numbers Table, assuming < 10,000 elements of delimited string 
SELECT TOP 10000 IDENTITY(int,1,1) AS id
    INTO #numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
ALTER TABLE #numbers ADD CONSTRAINT PK_numbers PRIMARY KEY CLUSTERED (id) WITH FILLFACTOR=100

--Create the new DataStore table, using the numhers table to split the string 

SELECT Datastore_Name, SUBSTRING(ESX_Hosts, id, CHARINDEX(',', ESX_Hosts + ',', id) - id) as ESX_Host
INTO #tbl_DatastoreNEW
FROM #numbers, #tbl_Datastore
WHERE id <= CONVERT(INT, LEN(ESX_Hosts))
AND SUBSTRING(',' + ESX_Hosts, id, 1) = ','
CREATE CLUSTERED INDEX Datastore_Name_EsX_HostClustered ON #tbl_DatastoreNEW (Datastore_Name ASC, ESX_Host ASC) WITH FILLFACTOR=100

--Now this will return the same as you SQL, without double wildcard or CROSS JOIN
select e.*, d.Datastore_Name
from #tbl_DatastoreNEW d 
	INNER JOIN #tbl_ESXHost e ON (d.ESX_Host = e.ESX_Host)
 
Soldato
OP
Joined
8 Mar 2005
Posts
3,676
Location
London, UK
Apologies was slightly off with the figures:
tbl1 - ~3000 rows
tbl2 -~1000 rows
The query in its current format generates ~12000 returned rows and it takes 10s of seconds to complete.
Nothing confidential here so :

Here's the full query:
SELECT tbl_ESXHosts.Host, tbl_ESXHosts.Model,
tbl_Datastore.Name, tbl_Datastore.CapacityMB,
tbl_Datastore.FreeMB, tbl_Datastore.FreePERCENT,
tbl_ESXHosts.Datacenter, tbl_ESXHosts.[#Memory] / 1024 AS RAM,
tbl_ESXHosts.VirtualCentre, tbl_ESXHosts.LastWriteTime,
tbl_ESXHosts.ESXVersion
FROM tbl_Datastore CROSS JOIN
tbl_ESXHosts
WHERE (tbl_Datastore.Hosts LIKE '%' + tbl_ESXHosts.Host + '%')

And links to the tables(csv):
http://mire.darkgen.net/~paul/tmp/

Gawping through the code in the interim.

Thanks, Paul.
 
Associate
Joined
16 Jan 2003
Posts
1,913
Seems very strange that the tables don't have a primary key specified, I would have created an int PK and would really be advisable.

I loaded your tables, all columns were varchar(max) and no indexes so your performance should be better.

Firstly - running your SQL
Code:
SELECT tbl_ESXHosts.Host, tbl_ESXHosts.Model, 
tbl_Datastore.Name, tbl_Datastore.CapacityMB, 
tbl_Datastore.FreeMB, tbl_Datastore.FreePERCENT, 
tbl_ESXHosts.Datacenter, tbl_ESXHosts.[#Memory] / 1024 AS RAM, 
tbl_ESXHosts.VirtualCentre, tbl_ESXHosts.LastWriteTime, 
tbl_ESXHosts.ESXVersion
into #test
FROM tbl_Datastore CROSS JOIN
tbl_ESXHosts
WHERE (tbl_Datastore.Hosts LIKE '%' + tbl_ESXHosts.Host + '%')
in management studio took 1min 5, 21132 rows
profiler:
CPU:64896, Reads:217510, duration:65057

Now you do need a numbers table for this, however even creating a temp table one each time it will still be much better than the cross join and double wildcard approach. The SQL below will return the same 21132 rows, but took 1 second, CPU=1341, Reads=66298, Duration=1653

Code:
--Numbers Table, assuming < 10,000 elements of delimited string 
SELECT TOP 10000 IDENTITY(int,1,1) AS id
    INTO #numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
	CROSS JOIN sys.objects s3
ALTER TABLE #numbers ADD CONSTRAINT PK_numbersTEST PRIMARY KEY CLUSTERED (id) WITH FILLFACTOR=100

--get the fields you want from tbl_Datastore, also parse the hosts so 1 row per host
SELECT tbl_Datastore.Name, tbl_Datastore.Address, tbl_Datastore.CapacityMB, tbl_Datastore.FreeMB, tbl_Datastore.FreePERCENT, 
 LTRIM(RTRIM(SUBSTRING(Hosts, id, CHARINDEX(',', Hosts + ',', id) - id))) as Host
INTO #tbl_DatastoreHostsAndInfo
FROM #numbers, tbl_Datastore
WHERE id <= CONVERT(INT, LEN(Hosts))
AND SUBSTRING(',' + Hosts, id, 1) = ','

--final select joins to tbl_ESXHosts to get the required fields, and uses table created above to get those for the data store. 
SELECT tbl_ESXHosts.Host, tbl_ESXHosts.Model, 
tbl_Datastore.Name, tbl_Datastore.CapacityMB, 
tbl_Datastore.FreeMB, tbl_Datastore.FreePERCENT, 
tbl_ESXHosts.Datacenter, tbl_ESXHosts.[#Memory] / 1024 AS RAM, 
tbl_ESXHosts.VirtualCentre, tbl_ESXHosts.LastWriteTime, 
tbl_ESXHosts.ESXVersion
FROM #tbl_DatastoreHostsAndInfo tbl_Datastore, tbl_ESXHosts
WHERE tbl_Datastore.Host = tbl_ESXHosts.Host

You could store the results of the #tbl_DatastoreHostsAndInfo as a persistent table and then put a trigger on tbl_Datastore for updates, inserts and deletes to keep the other table up-to-date however this is probably overkill as it comes back in a second.

It would be worth speaking to RVTools and asking them to store this differently (or as well). They may actually already do this as well so you could do a bit of digging in the database to see the following SQL will show any table in the current database that has a column with "host" in it.
Code:
select so.name, sc.name 
from sys.objects so, sys.columns sc
where so.type = 'U' --user table
AND so.object_id = sc.object_id
and sc.name like '%host%'
order by so.name, sc.name

Hopefully the above should help.
 
Soldato
OP
Joined
8 Mar 2005
Posts
3,676
Location
London, UK
Wow, understood re indexing. Many thanks for this, much appreciated and it will definitely assist in my approach in future. I'll pour over this in the morning and get back to you.

Thanks again, Paul.
 
Soldato
OP
Joined
8 Mar 2005
Posts
3,676
Location
London, UK
I couldn't wait and played and I think I'm geting there, bear with me :)

So I've included these few lines to check and delete whether the temp tables exist:

IF (SELECT object_id('numbers')) IS NOT NULL
BEGIN
DROP TABLE numbers
END

IF (SELECT object_id(tbl_vDatastoreHostsAndInfo')) IS NOT NULL
BEGIN
DROP TABLE tbl_vDatastoreHostsAndInfo
END

However, I'm getting multiple duplicated returned rows(13005) and the query is again running into 10s of seconds. Dropping DISTINCT into both queries will return just 1219 rows (less than a second) but only returns a single row for each host.
 
Last edited:
Associate
Joined
16 Jan 2003
Posts
1,913
If you use #TableName it creates a SQL Server temp table which will automatically be deleted by SQL server when that connection is closed. However as I have created a constraint for the primary key this might not get dropped, so change this to a clustered index.

If you copy the SQL below and run it, then open a new window and run it you shouldn't have any problem. i.e. you could have a scheduled job that ran this and inserted the results from the final select into another table, perhaps also select GETDATE() as DateRan and it should run without problem
Code:
--Numbers Table, assuming < 10,000 elements of delimited string, clustered index instead of PK 
SELECT TOP 10000 IDENTITY(int,1,1) AS id
    INTO #numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
	CROSS JOIN sys.objects s3
CREATE CLUSTERED INDEX id ON #numbers([id] ASC) WITH (FILLFACTOR = 90)

--get the fields you want from tbl_Datastore, also parse the hosts so 1 row per host
SELECT tbl_Datastore.Name, tbl_Datastore.Address, tbl_Datastore.CapacityMB, tbl_Datastore.FreeMB, tbl_Datastore.FreePERCENT, 
 LTRIM(RTRIM(SUBSTRING(Hosts, id, CHARINDEX(',', Hosts + ',', id) - id))) as Host
INTO #tbl_DatastoreHostsAndInfo
FROM #numbers, tbl_Datastore
WHERE id <= CONVERT(INT, LEN(Hosts))
AND SUBSTRING(',' + Hosts, id, 1) = ','

--final select joins to tbl_ESXHosts to get the required fields, and uses table created above to get those for the data store. 
SELECT tbl_ESXHosts.Host, tbl_ESXHosts.Model, 
tbl_Datastore.Name, tbl_Datastore.CapacityMB, 
tbl_Datastore.FreeMB, tbl_Datastore.FreePERCENT, 
tbl_ESXHosts.Datacenter, tbl_ESXHosts.[#Memory] / 1024 AS RAM, 
tbl_ESXHosts.VirtualCentre, tbl_ESXHosts.LastWriteTime, 
tbl_ESXHosts.ESXVersion
FROM #tbl_DatastoreHostsAndInfo tbl_Datastore, tbl_ESXHosts
WHERE tbl_Datastore.Host = tbl_ESXHosts.Host

If I change the final select to select distinct I get 21120 rows instead of 21132.
 
Soldato
OP
Joined
8 Mar 2005
Posts
3,676
Location
London, UK
Something is going awry - very odd.

But I think I'll have to call it a night... Appreciate your help and support.

Below is the code (with slightly changed identifers).

Code:
IF (SELECT object_id('numbers')) IS NOT NULL
BEGIN
    DROP TABLE numbers
END

IF (SELECT object_id('KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo')) IS NOT NULL
BEGIN
    DROP TABLE KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo
END

IF (SELECT object_id('numbers')) IS NOT NULL
BEGIN
    DROP TABLE numbers
END

IF (SELECT object_id('KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo')) IS NOT NULL
BEGIN
    DROP TABLE KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo
END

--Numbers Table, assuming < 10,000 elements of delimited string 
SELECT TOP 10000 IDENTITY(int,1,1) AS id
    INTO numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
	CROSS JOIN sys.objects s3
ALTER TABLE numbers ADD CONSTRAINT PK_numbersTEST PRIMARY KEY CLUSTERED (id) WITH FILLFACTOR=100

--get the fields you want from tbl_Datastore, also parse the hosts so 1 row per host
SELECT dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.Name, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.Address, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.CapacityMB, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.FreeMB, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.FreePERCENT, 
 LTRIM(RTRIM(SUBSTRING(Hosts, id, CHARINDEX(',', Hosts + ',', id) - id))) as Host
INTO dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo
FROM numbers, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore
WHERE id <= CONVERT(INT, LEN(Hosts))
AND SUBSTRING(',' + Hosts, id, 1) = ','

--final select joins to tbl_ESXHosts to get the required fields, and uses table created above to get those for the data store. 
SELECT dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Host, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Model, 
dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.Name, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.CapacityMB, 
dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.FreeMB, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.FreePERCENT, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Datacenter, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.[#Memory] / 1024 AS RAM, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.VirtualCentre, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.LastWriteTime, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.ESXVersion
FROM dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore, dbo.KOPSAWN00244_USPRD1448_RVT_vHost
WHERE dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.Hosts = dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Host
 
Associate
Joined
16 Jan 2003
Posts
1,913
You have 3 tables in your final where clause but only join two of them so have a cartestian.
Change your last select to this
Code:
--CHANGE IT TO THIS
SELECT dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Host, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Model, 
dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo.Name, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo.CapacityMB, 
dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo.FreeMB, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo.FreePERCENT, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Datacenter, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.[#Memory] / 1024 AS RAM, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.VirtualCentre, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.LastWriteTime, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.ESXVersion
FROM dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo , dbo.KOPSAWN00244_USPRD1448_RVT_vHost
WHERE dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo.Host = dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Host

below is all the code, I have assumed KOPSAWN00244_USPRD1448_RVT_vDatastore is tbl_Datastore
and KOPSAWN00244_USPRD1448_RVT_vHost is tbl_ESXHosts
from the csv files provided.

Code:
IF (SELECT object_id('numbers')) IS NOT NULL
BEGIN
    DROP TABLE numbers
END

IF (SELECT object_id('KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo')) IS NOT NULL
BEGIN
    DROP TABLE KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo
END

IF (SELECT object_id('numbers')) IS NOT NULL
BEGIN
    DROP TABLE numbers
END

IF (SELECT object_id('KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo')) IS NOT NULL
BEGIN
    DROP TABLE KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo
END

--Numbers Table, assuming < 10,000 elements of delimited string 
SELECT TOP 10000 IDENTITY(int,1,1) AS id
    INTO numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
	CROSS JOIN sys.objects s3
ALTER TABLE numbers ADD CONSTRAINT PK_numbersTEST PRIMARY KEY CLUSTERED (id) WITH FILLFACTOR=100


IF (SELECT object_id('KOPSAWN00244_USPRD1448_RVT_vHost')) IS NOT NULL
BEGIN
    DROP TABLE KOPSAWN00244_USPRD1448_RVT_vHost
END
--assuming KOPSAWN00244_USPRD1448_RVT_vDatastore is tbl_Datastore
select * into KOPSAWN00244_USPRD1448_RVT_vDatastore FROM tbl_Datastore
--assuming KOPSAWN00244_USPRD1448_RVT_vHost is tbl_ESXHosts
select * into KOPSAWN00244_USPRD1448_RVT_vHost FROM tbl_ESXHosts

--get the fields you want from tbl_Datastore, also parse the hosts so 1 row per host
SELECT dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.Name, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.Address, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.CapacityMB, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.FreeMB, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.FreePERCENT, 
 LTRIM(RTRIM(SUBSTRING(Hosts, id, CHARINDEX(',', Hosts + ',', id) - id))) as Host
INTO dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo
FROM numbers, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore
WHERE id <= CONVERT(INT, LEN(Hosts))
AND SUBSTRING(',' + Hosts, id, 1) = ','

--final select joins to tbl_ESXHosts to get the required fields, and uses table created above to get those for the data store. 
--LAST TABLE - YOU HAVE 3 TABLES IN WHERE CLAUSE BUT ONLY JOINING TO TWO, SO CARTESIAN!
--THIS WILL RUN FOR AGES AND ISNT WHAT YOU WANT
/*
SELECT dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Host, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Model, 
dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.Name, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.CapacityMB, 
dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.FreeMB, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.FreePERCENT, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Datacenter, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.[#Memory] / 1024 AS RAM, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.VirtualCentre, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.LastWriteTime, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.ESXVersion
FROM dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore, dbo.KOPSAWN00244_USPRD1448_RVT_vHost
WHERE dbo.KOPSAWN00244_USPRD1448_RVT_vDatastore.Hosts = dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Host
*/

--CHANGE IT TO THIS
SELECT dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Host, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Model, 
dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo.Name, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo.CapacityMB, 
dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo.FreeMB, dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo.FreePERCENT, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Datacenter, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.[#Memory] / 1024 AS RAM, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.VirtualCentre, dbo.KOPSAWN00244_USPRD1448_RVT_vHost.LastWriteTime, 
dbo.KOPSAWN00244_USPRD1448_RVT_vHost.ESXVersion
FROM dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo , dbo.KOPSAWN00244_USPRD1448_RVT_vHost
WHERE dbo.KOPSAWN00244_USPRD1448_RVT_vDatastoreHostsAndInfo.Host = dbo.KOPSAWN00244_USPRD1448_RVT_vHost.Host
 
Last edited:
Soldato
OP
Joined
8 Mar 2005
Posts
3,676
Location
London, UK
Ahhh, yes. What a wally.

Many thanks, its now returning expected results and in less than a second. Brilliant. Really appreciate your assistancew on this.

Cheers, Paul.
 
Back
Top Bottom