September 2, 2005 at 11:34 pm
Ive just upgraded my site from using mysql to mssql, and im having trouble with a query.
This is the query which i have in mysql, what it does is select all the records which the firstname or the surname match a certain character as the first character.
e.g.
if the first letter was A it would return
andrea smith
adam johnston
azaz, kristy
what the if statement does is works out if the firstname or surname starts with A. The if the firstname starts with a it return firstname surname but if the surname starts with A it will return surname, firstname
MYSQL CODE
SELECT IF(surname LIKE '" & arrCharacters(0) & "%',TRIM(CONCAT(surname, ', ', firstname)),TRIM(CONCAT(firstname, ' ', surname))) AS fullname FROM tblPeople WHERE surname LIKE '"& arrCharacters(0) &"%' OR firstname LIKE '"& arrCharacters(0) &"%' ORDER BY fullname
Thanks in advance.
September 3, 2005 at 7:43 am
Select case when Surname like 'A%' then Surname + ', ' + FirstName
when FirstName like 'A%' then FirstName + ', ' + Surname
end
from....
BTW this is something that would be faster to handle at the client. The server is meant to sent the data, the client to present it and this is really a presentation issue.
September 4, 2005 at 12:47 pm
Agree with Remi, this sounds weird for the database to handle. But if needed I would probably code it like this:
SELECT fullname FROM (
SELECT firstname + ',' + surname as fullname
FROM tblpeople
WHERE firstname LIKE 'A%'
UNION
SELECT surname + ',' + firstname
FROM tblpeople
WHERE surname LIKE 'A%'
) foo
ORDER BY fullname
September 4, 2005 at 12:59 pm
Chris, Is the union faster then using a CASE in the derived table?
select foo.FullName from
(Select case when lname like 'A%' then lname + ', ' + fName when fName like 'A%' then fName + ', ' + lname end as FullName from tblPeople) foo
order by fullname
Dave
Trainmark.com IT Training B2B Marketplace
(Jobs for IT Instructors)
September 4, 2005 at 1:30 pm
No it's faster (assuming it is) because both search condition can use a single index seek, instead of possibly a scan. So I'd definitly check out the union version.
September 4, 2005 at 2:48 pm
Cool I'll have to test that. I would have assumed otherwise.
I would have assumed the derived table would use an index seek to get the records and then all the outter statement has to do is order them. The derived table is not indexed so I guess it wouldn't use the index for the ordering.
I'll have to run them both through the QA later and check out the execution plan. I use allot of derived tables in one project and maybe I should be doing a union.
Dave
Trainmark.com IT Training B2B Marketplace
(Jobs for IT Instructors)
September 5, 2005 at 12:09 am
Note the WHERE clauses. If we where to select all the rows and just decide if firstname or surname should come first in fullname, then the union would be much slower. But since we are only after rows where either firstname or surname starts with the character A we need to apply the WHERE clause. For the case statement we would need a clause like "firstname = 'A%' OR surname = 'A%'", and depending on indexing we might get in trouble with that. Anyway I think the union is clearer on what the query does.
September 5, 2005 at 3:50 am
I run a quick test in QA and it looks like a single derived table is faster.
In my test db neither family nor givennames are indexed. It also has a very small number of total rows.
I ran thissingle derived table)
--------------
select foo.FullName from
(Select case when familyname like 'A%' then familyname + ', ' + givenName when givenName like 'A%' then givenName + ' ' + familyname end as FullName from tblInstructors
where
familyname like 'A%' or givenname like 'A%'
) foo
order by fullname
--------------
And then this: (union join)
--------------
SELECT fullname FROM (SELECT givenname + ',' + familyname as fullnameFROM tblinstructors
WHERE givenname LIKE 'A%' UNION
SELECT familyname + ',' + givenname
FROM tblInstructors
WHERE familyname LIKE 'A%'
) foo
ORDER BY fullname
The union method does two index scans for a total of 90% of the execution time (45% each).
The single derived table does one index scan for 83%.
In all the union method shows six steps in the plane to the others three.
I suppose I could populate a table big enough to measure the time difference but it looks like the Union is less performant. Which is what my assumptions was.
Am I missing something? Are the two index scans in the union "happening" at the same time?
BTW: I am only pulling at these threads because I need to challenge my assumptions and to keep learning
Dave
Trainmark.com IT Training B2B Marketplace
(Jobs for IT Instructors)
September 5, 2005 at 4:55 am
Naturally, without indexes scans will be necessary, and then the unions will perform worse since two scans are required.
September 5, 2005 at 11:05 am
I ran both queries again first with one index (lname) then with both lname,fname. When I run them both in the same QA window it shows a percent cost relative to the batch. The union version comes out to 60% the single derived table 40%. When I used the covering index the results were closer at 52%/48%.
I used With(index()) to force the use of each index in turn.
Interestingly enough the derived table method always did an index scan and never a seek. Whereas the union would use a seek when it could. I supppose this is your point. Perhaps with a much large table to results would skew the other way, maybe allot. (test table only has a few thousands rows).
In any case I sure am having fun with QA these days Thanks.
Dave
Trainmark.com IT Training B2B Marketplace
(Jobs for IT Instructors)
September 5, 2005 at 11:09 am
Hmm something weird. I just ran it again but in I fixed my union statement so that each select used the correct index. eg. where fname used the fname index and where lname used the lnmae index.
In the execution plan it showed queries in the union statements using index seeks but the cost relative to batch jumped up to 83% ?? I would have expected the cost to go down?
Maybe I am reading the numbers backwards?
Dave
Trainmark.com IT Training B2B Marketplace
(Jobs for IT Instructors)
September 5, 2005 at 6:50 pm
"TheKing",
Several solutions have been posted to your problem... did any of them do what you wanted?
--Jeff Moden
Change is inevitable... Change for the better is not.
September 5, 2005 at 7:02 pm
Have you tried with a covering index (1 index with both columns) and checking the derived table version?
September 5, 2005 at 7:40 pm
Yes I did. The result using that index was 60/40 in favor of the derived table method.
When I wrote the UNION so that each select uses the appropriate index for each where claus (fname or lname) the cost went to 80% when compared to the derived table using the covering index.
Here is a screenie of the QA.
http://www.lonecrow.net/qa.gif
Dave
Trainmark.com IT Training B2B Marketplace
(Jobs for IT Instructors)
September 5, 2005 at 8:42 pm
Hmm, I meant the single query with a covering index (where both columns are in ONE index).
Viewing 15 posts - 1 through 15 (of 19 total)
You must be logged in to reply to this topic. Login to reply