Могу ли я реорганизовать свои запросы MySQL в один запрос на основе количества результатов? - PullRequest
1 голос
/ 20 сентября 2008

У меня есть таблица y, в которой есть два столбца a и b

Записи:

a   b

1   2

1   3

1   4

0   5

0   2

0   4

Я хочу получить 2,3,4, если я ищу столбец a для 1, и 5,2,4, если я ищу столбец a.

Итак, если я ищу A для чего-то, что находится в A, (1) я получаю эти строки, и если нет записей A для данного значения, дайте мне значения по умолчанию (a = '0')

Вот как бы я знал, как это сделать:

$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;');

Итак, теперь, когда это достаточно объяснено, как мне это сделать в одном запросе и как насчет проблем с производительностью?

Наиболее используемой частью будет третий запрос, поскольку в a будут только значения для числа ЕСЛИ вы отклоняетесь от значений по умолчанию.

Ответы [ 6 ]

2 голосов
/ 20 сентября 2008

Я думаю, что у меня есть:

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

Он проверяет, существует ли @value в таблице, если нет, то по умолчанию используется 0. @value также может быть значением php.

Надеюсь, это поможет:)

2 голосов
/ 20 сентября 2008

Вы можете попробовать что-то вроде этого. Я не уверен на 100%, что это сработает, потому что count () - агрегатная функция, но ее стоит попробовать.

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
)
1 голос
/ 23 сентября 2008

Мне кажется, Михал Кралик - лучший ответ на мой взгляд, основанный на производительности сервера. Делать отборы или хранимые процедуры для такой простой логики действительно не стоит.

Единственный способ улучшить логику Михала - это выполнить этот запрос несколько раз в одном скрипте. В этом случае я сначала запросил бы 0, а затем выполнил каждый отдельный запрос, а затем проверил, было ли какое-либо значение.

Псевдо-код

// 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;
1 голос
/ 20 сентября 2008

А как же

$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";
  }
}

Один запрос, но накладные расходы, если много «нулевых» значений.
Зависит, если вы заботитесь о накладных расходах ...

0 голосов
/ 20 сентября 2008

Я не знаю, почему это было отмечено - пожалуйста, просветите меня. Это действительная, проверенная хранимая процедура, и я ответил на вопрос. ОП не требует, чтобы ответ был в php. ??

Вот хранимый процесс для выполнения того, что вы хотите, который работает в SQL Server. Я не уверен насчет 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

Вы бы запустили это (на сервере sql) с

GetRealElseGetDefault 1

Основываясь на быстром поиске в Google, MySQL быстро существует. Это было бы особенно быстро, если колонка А проиндексирована. Если ваша таблица достаточно велика, чтобы вы беспокоились о ее производительности, возможно, она достаточно велика для индексации.

0 голосов
/ 20 сентября 2008

Вы можете сделать все это в одной хранимой процедуре с одним параметром.

Мне нужно закончить, но я постараюсь написать для вас и добавить сюда, как только вернусь с поручением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...