Я бы предложил использовать метод private friend
, который реализует прикладную логику конструктора и вызывается различными конструкторами. Вот пример:
Предположим, у нас есть класс с именем StreamArrayReader
с некоторыми закрытыми полями:
private:
istream * in;
// More private fields
И мы хотим определить два конструктора:
public:
StreamArrayReader(istream * in_stream);
StreamArrayReader(char * filepath);
// More constructors...
Когда второй просто использует первый (и, конечно, мы не хотим дублировать реализацию первого). В идеале, хотелось бы сделать что-то вроде:
StreamArrayReader::StreamArrayReader(istream * in_stream){
// Implementation
}
StreamArrayReader::StreamArrayReader(char * filepath) {
ifstream instream;
instream.open(filepath);
StreamArrayReader(&instream);
instream.close();
}
Однако, это не разрешено в C ++. По этой причине мы можем определить метод закрытого друга следующим образом, который реализует то, что должен делать первый конструктор:
private:
friend void init_stream_array_reader(StreamArrayReader *o, istream * is);
Теперь этот метод (потому что это друг) имеет доступ к закрытым полям o
. Затем первый конструктор становится:
StreamArrayReader::StreamArrayReader(istream * is) {
init_stream_array_reader(this, is);
}
Обратите внимание, что это не создает несколько копий для вновь созданных копий. Вторым становится:
StreamArrayReader::StreamArrayReader(char * filepath) {
ifstream instream;
instream.open(filepath);
init_stream_array_reader(this, &instream);
instream.close();
}
То есть вместо того, чтобы один конструктор вызывал другого, оба вызывают частного друга!
SELECT Item.ID, Item.Name ОТ Пункт ГДЕ Item.ID IN ( ВЫБЕРИТЕ ItemTag.ItemID ОТ ItemTag ГДЕ ItemTag.TagID = 57 ИЛИ ItemTag.TagID = 55)
или
ВЫБРАТЬ Item.ID, Item.Name ОТ Пункт ВЛЕВО ПРИСОЕДИНИТЬСЯ к ItemTag НА ItemTag.ItemID = Item.ID ГДЕ ItemTag.TagID = 57 ИЛИ ItemTag.TagID = 55 ГРУППА ПО ПУНКТУ.ID
SELECT Item.ID, Item.Name FROM Item JOIN ( SELECT DISTINCT ItemID FROMT ItemTag WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55 ) tags ON tags.ItemID = Item.ID
, но этот немного менее эффективен, чем
IN
илиEXISTS
.См. Эту статью в моем блоге для более подробного сравнения производительности:
Я думаю, это будет зависеть от того, как оптимизатор обрабатывает их, может даже случиться так, что вы получите такую же производительность. План выполнения медийной рекламы - ваш друг.
SELECT Item.ID, Item.Name
...
GROUP BY Item.ID
Это недопустимый T-SQL. Item.Name должно появляться в предложении group by или в агрегатной функции, например SUM или MAX.
Практически невозможно (если только вы не один из тех сумасшедших администраторов баз данных-гуру), что будет быстро, а что нет, не глядя на план выполнения и / или выполняя некоторые стресс-тесты. .
запустите это:
SET SHOWPLAN_ALL ON
затем запустите каждую версию запроса
, вы можете увидеть, возвращают ли они тот же план, а если нет, посмотрите TotalSubtreeCost в первой строке каждого и посмотрите, насколько они разные.
Кажется, что производительность всегда имеет решающее значение, но вы также слышите, что «дешевле покупать оборудование, чем программисты»
Второй выигрывает по производительности.
Иногда приятно смотреть в SQL и знаю цель, но для этого нужны комментарии. В первом запросе для фильтра используется другая таблица - довольно просто.
Второй запрос имеет больше смысла (с точки зрения понимания цели, а не производительности) с использованием отдельной таблицы вместо группировки по. Я ожидал, что некоторые агрегаты будут в списке, но их нет. Скорость убивает.