tags:

views:

347

answers:

6

I have a table y Which has two columns a and b

Entries are

a b

1 2

1 3

1 4

0 5

0 2

0 4

I want to get 2,3,4 if I search column a for 1, and 5,2,4 if I search column a.

So, if I search A for something that is in A, (1) I get those rows, and if there are no entries A for given value, give me the 'Defaults' (a = '0')

Here is how I would know how to do it.

$r = mysql_query('SELECT `b` FROM `y` WHERE `a` = \'1\';');
//This gives desired results, 3 rows

$r = mysql_query('SELECT `b` FROM `y` WHERE `a` = \'2\';');
//This does not give desired results yet.
//Get the number of rows, and then get the 'defaults'
if(mysql_num_rows($r) === 0) $r = mysql_query('SELECT `b` FROM `y` WHERE `a` = 0;');

So, now that it's sufficiently explained, how do I do that in one query, and what about performance concerns? The most used portion would be the third query, because there would only be values in a for a number IF you stray from the defaults.

A: 

You can do all this in a single stored procedure with a single parameter.

I have to run out, but I'll try to write one up for you and add it here as soon as I get back from my errand.

Cade Roux
Great. I'm completely inept when it comes to stored procedures.In general, I would only ask if doing it in a stored procedure would be better than the php version that I proposed above. My instinct would say 'yes, if the database is on a different server, and not really otherwise'..
Issac Kelly
Stored procedures are always better. The solutions given by the others are fine, but yes, in general, sending the database as much information as your client can to return as little information as you need is generally good, and it really doesn't matter if the client is separate machine than server
Cade Roux
A: 

I don't know why this was marked down - please educate me. It is a valid, tested stored procedure, and I answered the question. The OP didn't require that the answer be in php. ??

Here's a stored proc to do what you want that works in SQL Server. I'm not sure about MySQL.

create proc GetRealElseGetDefault (@key as int)
as
begin

-- Use this default if the correct data is not found
declare @default int
select @default = 0

-- See if the desired data exists, and if so, get it.  
-- Otherwise, get defaults.
if exists (select * from TableY where a = @key)
    select b from TableY where a = @key
else
    select b from TableY where a = @default

end -- GetRealElseGetDefault

You would run this (in sql server) with

GetRealElseGetDefault 1

Based on a quick google search, exists is fast in MySQL. It would be especially fast is column A is indexed. If your table is large enough for you to be worried about performance, it is probably large enough to index.

CindyH
I don't know why this was marked down - please educate me. It is a valid, tested stored procedure, and I answered the question. The OP didn't require that the answer be in php. ??
CindyH
+2  A: 

You can try something like this. I'm not 100% sure it will work because count() is a aggregate function but its worth a shot.

SELECT b
FROM table1 
WHERE a = (
   SELECT
     CASE count(b)
       WHEN 0 THEN :default_value
       ELSE :passed_value 
     END
   FROM table1
   WHERE a = :passed_value
)
Lawrence Barsanti
I guess that I can't accept two answers, but these are both right, I tested them, and I've voted them both up as best as I could.
Issac Kelly
+1  A: 

What about

$rows = $db->fetchAll('select a, b FROM y WHERE a IN (2, 0) ORDER BY a DESC');
if(count($rows) > 0) {
  $a = $rows[0]['a'];
  $i = 0;
  while($rows[$i]['a'] === $a) {
    echo $rows[$i++]['b']."\n";
  }
}

One query, but overhead if there are a lot of 'zero' values.
Depends if you care about the overhead...

michal kralik
+2  A: 

I think I have it:

SELECT b FROM y where a=if(@value IN (select a from y group by a),@value,0);

It checks if @value exists in the table, if not, then it uses 0 as a default. @value can be a php value too.

Hope it helps :)

Jonathan
I chose this one because it has only an IF, and the other is a case, so since I was choosing between two items only, this seemed only slightly more correct.
Issac Kelly
+1  A: 

I think Michal Kralik best answer in my opinion based on server performance. Doing subselects or stored procedures for such simple logic really is not worth it.

The only way I would improve on Michal's logic is if you are doing this query multiple times in one script. In this case I would query for the 0's first, and then run each individual query, then checking if there was any value.

Pseudo-code

// get the value for hte zero's
$zeros = $db->fetchAll('select a, b FROM y WHERE a = 0');

//checking for 1's
$ones = $db->fetchAll('select a, b FROM y WHERE a = 1');
if(empty($ones)) $ones = $zeros;

//checking for 2's
$twos = $db->fetchAll('select a, b FROM y WHERE a = 2');
if(empty($twos)) $twos = $zeros;

//checking for 3's
$threes = $db->fetchAll('select a, b FROM y WHERE a = 3');
if(empty($threes)) $threes = $zeros;
Jacob