использовать коррелированный подзапрос
select product_id , a.customer_id , age
from purchases a inner join customers b on a.customer_id =b.customer_id
where age in (select max(age) from purchases a1 inner join customers b1 on a1.customer_id =b1.customer_id where a.product_id=a1.product_id group by a1.product_id)
Я предложил бы использовать ассоциативный массив, чтобы передать названный параметрами, но сохранить их в массиве, не извлекая их.
function myFunc(array $args) {
echo "Hi, " . $args['name'];
// etc
}
Существует несколько причин этого. Смотря на ту функцию, можно вполне ясно видеть, что я обращаюсь к одному из аргументов, переданных в функцию. Если Вы извлекаете их и не замечаете extract()
Вы (или следующий парень) будете там царапать голову, задающуюся вопросом где это"$name
"переменная прибыла из. Даже если Вы действительно знаете об извлечении аргументов локальным переменным это - все еще игра предположения до известной степени.
Во-вторых, это гарантирует, что другой код не перезаписывает args. Вы, возможно, записали свою функцию, ожидая только называть аргументы $foo
и $bar
, таким образом в Вашем другом коде, Вы определяете $baz = 8;
, например. Позже, Вы могли бы хотеть развернуть свою функцию, чтобы взять новый параметр, названный "baz", но забыть заменять Ваши другие переменные, поэтому независимо от того, что передается в аргументах, $baz
будет всегда устанавливаться на 8.
Существуют некоторые преимущества для использования массива также (они применяются одинаково к методам извлечения или отъезда в массиве): можно настроить переменную во главе каждой вызванной функции $defaults
:
function myFunc (array $args) {
$default = array(
"name" => "John Doe",
"age" => "30"
);
// overwrite all the defaults with the arguments
$args = array_merge($defaults, $args);
// you *could* extract($args) here if you want
echo "Name: " . $args['name'] . ", Age: " . $args['age'];
}
myFunc(array("age" => 25)); // "Name: John Doe, Age: 25"
Вы могли даже удалить все объекты из $args
которые не имеют соответствия $default
значение. Таким образом, Вы знаете точно, какие переменные Вы имеете.
Вот иначе, Вы могли сделать это.
/**
* Constructor.
*
* @named string 'algorithm'
* @named string 'mode'
* @named string 'key'
*/
public function __construct(array $parameter = array())
{
$algorithm = 'tripledes';
$mode = 'ecb';
$key = null;
extract($parameter, EXTR_IF_EXISTS);
//...
}
С настроенным, Вы получаете параметрические усилители по умолчанию, Вы не теряете intellisense в IDE, и EXTR_IF_EXISTS заставляет его защитить, просто извлекая ключи массива, которые являются уже существующими как переменные.
(Между прочим, создавая значения по умолчанию из примера Вы обеспечили, не хорошо, потому что, если массив параметрического усилителя обеспечивается без индекса 'имени', Ваше значение по умолчанию потеряно.)
По моему опыту, этот подход действительно только выгоден, если одна из двух вещей верна
someFunc( null, null, null, null, 1 );
Если любой из них верен для Вас, фальсифицирование, названное параметрическими усилителями с ассоциативным массивом, могло бы быть правильной реализацией. Кроме знания, когда избежать извлечения (или предотвращение его в целом) я не могу сразу думать о других оборотных сторонах.
Однако часто обе из этих проблем могут быть решены посредством рефакторинга также.