Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jan 3rd, 2008, 4:34 PM   #1
kurifu
Expert Programmer
 
kurifu's Avatar
 
Join Date: Jul 2004
Location: Halifax, Nova Scotia (Canada)
Posts: 784
Rep Power: 5 kurifu is on a distinguished road
Send a message via ICQ to kurifu Send a message via MSN to kurifu
Complex SQL Question Question

Hey guys; Trying to optimize some code that I wrote to not kill our DB server, I was hoping someone could give me some insightful feedback, as googling this isn't very easy.

Basically I have some cats in a database table, all with their own id. Each cat gets certain vaccinations, but never all at once. So I have another table where a record is inserted in a column indicating which shots they have received and when. There is a single column for each of these vaccinations, I put a "y" in it when complete.

So I want to generate a report which displays shots not administered, right now I grab each cat id, and loop through each one finding which ones are done, and which are not.

I am hoping I can take a single query and filter out results which have a Y in each column, problem is that this can be over multiple records. This will save a HUGE load on the DB. Any input?

Thanks,.
__________________
Clifford Matthew Roche <geek@cliffordroche.com>
Web Hosting: http://www.crd-hosting.com
Consulting: http://www.crdev-consulting.com
kurifu is offline   Reply With Quote
Old Jan 3rd, 2008, 4:51 PM   #2
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,032
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
Re: Complex SQL Question Question

Could you clarify your question, or how the tables are set up, so someone can give the right answer? Maybe even an example of what's in the DB would be great.

But I would have the tables set up so I can just do something like:

SELECT cat_id, vaccination_id FROM shots_table WHERE complete = 'n' ORDER BY cat_id

Then each row will be all the shots that the cat didn't receive, for each cat, ordered by the cat that didn't receive it. That is if this is how your tables are set up. But this seems way too simple an answer.
Sane is offline   Reply With Quote
Old Jan 3rd, 2008, 6:04 PM   #3
mbd
Programmer
 
Join Date: Nov 2007
Posts: 86
Rep Power: 1 mbd is on a distinguished road
Re: Complex SQL Question Question

assuming one cat has many vaccinations and you want to find cats without any vaccinations
sql Syntax (Toggle Plain Text)
  1. SELECT * FROM cats
  2. LEFT OUTER JOIN vaccinations
  3. ON vaccinations.cat_id = cats.cat_id
  4. WHERE vaccinations.cat_id IS NULL
mbd is offline   Reply With Quote
Old Jan 3rd, 2008, 10:29 PM   #4
Jimbo
Battle Programmer
 
Jimbo's Avatar
 
Join Date: Feb 2006
Location: Bellevue, WA, USA
Posts: 769
Rep Power: 3 Jimbo is on a distinguished road
Re: Complex SQL Question Question

Not knowing how many columns there are, is it feasible to do something like this:
sql Syntax (Toggle Plain Text)
  1. SELECT *
  2. FROM Cats c
  3. LEFT OUTER JOIN Vaccinations v ON c.cat_id = v.cat_id
  4. WHERE v.vaccination1 != 'Y' OR v.vaccination2 != 'Y' OR ...

Otherwise, what if you redid the database like this:
Cats (Id (PK), Name, Owner, whatever)
Vaccinations (Id(PK), Name, whatever)
Cat_Vacs (CatId (FK), VacId (FK))
and then used a query like this:
sql Syntax (Toggle Plain Text)
  1. SELECT c.Id, c.Name
  2. FROM Cats c LEFT OUTER JOIN
  3. Cat_Vacs cv ON c.Id = cv.CatId
  4. GROUP BY c.Id, c.Name
  5. HAVING COUNT(cv.VacId) < (SELECT COUNT(*) FROM Vaccinations))
Logical idea: get all cats who haven't had the number of vaccines in the Vaccines table.

Of course, this is technically 2 queries, but the inner one will be quick (the DB will know how many rows are in the table so this query is easily optimized internally).
__________________
<insert disclaimer here>
<insert shameless plug for Visual Studio here>
Jimbo is offline   Reply With Quote
Old Jan 4th, 2008, 12:56 AM   #5
kurifu
Expert Programmer
 
kurifu's Avatar
 
Join Date: Jul 2004
Location: Halifax, Nova Scotia (Canada)
Posts: 784
Rep Power: 5 kurifu is on a distinguished road
Send a message via ICQ to kurifu Send a message via MSN to kurifu
Re: Complex SQL Question Question

I always thought that LEFT OUTER JOIN required matching records in both tables, now that I know it does not, it should actually work very well. Thanks.
__________________
Clifford Matthew Roche &lt;geek@cliffordroche.com&gt;
Web Hosting: http://www.crd-hosting.com
Consulting: http://www.crdev-consulting.com
kurifu is offline   Reply With Quote
Old Jan 4th, 2008, 2:09 PM   #6
kurifu
Expert Programmer
 
kurifu's Avatar
 
Join Date: Jul 2004
Location: Halifax, Nova Scotia (Canada)
Posts: 784
Rep Power: 5 kurifu is on a distinguished road
Send a message via ICQ to kurifu Send a message via MSN to kurifu
Re: Complex SQL Question Question

Ok, so officially this is what solved my problem, and despite the number of inner queries, it runs much much faster...

SELECT DISTINCT cat_id, cat_name, cst_status, cat_birthday, cat_intake_date, CONVERT(VARCHAR(10), cat_birthday, 111) AS [YYYY/MM/DD]
FROM MEOW_Cats
LEFT JOIN MEOW_CatsStatus ON MEOW_Cats.cat_id = MEOW_CatsStatus.cst_cat_id
WHERE (cst_status <> 'D' AND cst_status <> 'R' AND cst_status <> 'C') AND
(SELECT COUNT(*) FROM MEOW_HealthRecords WHERE hre_cat_id = cat_id AND hre_fvrcpc_initial = 'Y') = 0 OR
(SELECT COUNT(*) FROM MEOW_HealthRecords WHERE hre_cat_id = cat_id AND hre_fvrcpc_booster = 'Y') = 0 OR
(SELECT COUNT(*) FROM MEOW_HealthRecords WHERE hre_cat_id = cat_id AND hre_fevl_initial = 'Y') = 0 OR
(SELECT COUNT(*) FROM MEOW_HealthRecords WHERE hre_cat_id = cat_id AND hre_fevl_booster = 'Y') = 0 OR
(SELECT COUNT(*) FROM MEOW_HealthRecords WHERE hre_cat_id = cat_id AND hre_rabies = 'Y') = 0 OR
(SELECT COUNT(*) FROM MEOW_HealthRecords WHERE hre_cat_id = cat_id AND hre_deworm = 'Y') = 0 OR
(SELECT COUNT(*) FROM MEOW_HealthRecords WHERE hre_cat_id = cat_id AND hre_alter = 'Y') = 0 
ORDER BY cat_name ASC
__________________
Clifford Matthew Roche &lt;geek@cliffordroche.com&gt;
Web Hosting: http://www.crd-hosting.com
Consulting: http://www.crdev-consulting.com
kurifu is offline   Reply With Quote
Old Jan 4th, 2008, 2:26 PM   #7
mbd
Programmer
 
Join Date: Nov 2007
Posts: 86
Rep Power: 1 mbd is on a distinguished road
Re: Complex SQL Question Question

try modifying your query to use this approach. i have no way of testing this, but i think you could eliminate those subqueries
sql Syntax (Toggle Plain Text)
  1. SELECT DISTINCT cat_id, cat_name, cst_status, cat_birthday, cat_intake_date, CONVERT(VARCHAR(10), cat_birthday, 111) AS [YYYY/MM/DD]
  2. FROM MEOW_Cats
  3. LEFT JOIN MEOW_CatsStatus ON MEOW_Cats.cat_id = MEOW_CatsStatus.cst_cat_id
  4. JOIN MEOW_HealthRecords ON hre_cat_id = cat_id
  5. WHERE hre_fvrpc_initial != 'Y' OR hre_fvrcpc_booster != 'Y' ...
mbd is offline   Reply With Quote
Old Jan 4th, 2008, 9:32 PM   #8
Jimbo
Battle Programmer
 
Jimbo's Avatar
 
Join Date: Feb 2006
Location: Bellevue, WA, USA
Posts: 769
Rep Power: 3 Jimbo is on a distinguished road
Re: Complex SQL Question Question

So, are the counts ever going to be more than 1? If so, presumably that means that either the cat will have to get another one in the future and you maybe should somehow be tracking the date it was last administered, unless getting the shot extra times is optional. If not, then using the inner query will be a performance cost, as you're doing a join and a projection for each sub-query when you could just do the join once and compare to each column.
__________________
<insert disclaimer here>
<insert shameless plug for Visual Studio here>
Jimbo is offline   Reply With Quote
Old Jan 8th, 2008, 12:52 PM   #9
kurifu
Expert Programmer
 
kurifu's Avatar
 
Join Date: Jul 2004
Location: Halifax, Nova Scotia (Canada)
Posts: 784
Rep Power: 5 kurifu is on a distinguished road
Send a message via ICQ to kurifu Send a message via MSN to kurifu
Re: Complex SQL Question Question

Quote:
Originally Posted by mbd View Post
try modifying your query to use this approach. i have no way of testing this, but i think you could eliminate those subqueries
sql Syntax (Toggle Plain Text)
  1. SELECT DISTINCT cat_id, cat_name, cst_status, cat_birthday, cat_intake_date, CONVERT(VARCHAR(10), cat_birthday, 111) AS [YYYY/MM/DD]
  2. FROM MEOW_Cats
  3. LEFT JOIN MEOW_CatsStatus ON MEOW_Cats.cat_id = MEOW_CatsStatus.cst_cat_id
  4. JOIN MEOW_HealthRecords ON hre_cat_id = cat_id
  5. WHERE hre_fvrpc_initial != 'Y' OR hre_fvrcpc_booster != 'Y' ...
This won't work because there are multiple health records per cat, the WHERE clause would always return true, returning multiple records for each cat.

I should add that even when using multiple subqueries this improved DB performance by a massive amount.
__________________
Clifford Matthew Roche &lt;geek@cliffordroche.com&gt;
Web Hosting: http://www.crd-hosting.com
Consulting: http://www.crdev-consulting.com
kurifu is offline   Reply With Quote
Old Jan 8th, 2008, 1:38 PM   #10
mbd
Programmer
 
Join Date: Nov 2007
Posts: 86
Rep Power: 1 mbd is on a distinguished road
Re: Complex SQL Question Question

i suspect that your database is not normalized
mbd is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Question regarding data input into PHP/Mysql using something other than GET davil PHP 6 Nov 20th, 2007 9:06 AM
SQL: Rewrite a complex join without #temp tables? jonyzz Other Scripting Languages 1 Sep 5th, 2007 11:51 AM
How to post a question nnxion C++ 10 Jun 3rd, 2005 12:53 PM
How to post a question nnxion C++ 0 Jun 3rd, 2005 9:55 AM
How to post a question nnxion C 0 Jun 3rd, 2005 9:55 AM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 11:29 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC