==
сравнивает ссылки на объекты.
.equals()
сравнивает значения String.
Иногда ==
дает иллюзии сравнения значений String, как в следующих случаях:
String a="Test";
String b="Test";
if(a==b) ===> true
Это связано с тем, что при создании любого строкового литерала JVM сначала ищет этот литерал в пуле строк, и если он найдет совпадение, эта же ссылка будет передана новой String. Из-за этого получаем:
(a == b) ===> true
String Pool
b -----------------> "test" <-----------------a
Однако ==
не выполняется в следующем случае:
String a="test";
String b=new String("test");
if (a==b) ===> false
В этом случае для new String("test")
оператор new String будет создан в куче, и эта ссылка будет указана на b
, поэтому b
будет дана ссылка на кучу, а не на String pool.
Теперь a
указывает на String в пуле String, а b
указывает на String в куче. Из-за этого мы получаем:
, если (a == b) ===> false.
String Pool
"test" <-------------------- a
Heap
"test" <-------------------- b
Пока .equals()
всегда сравнивает значение String, поэтому дает true в обоих случаях:
String a="Test";
String b="Test";
if(a.equals(b)) ===> true
String a="test";
String b=new String("test");
if(a.equals(b)) ===> true
Таким образом, использование .equals()
всегда лучше.
Вы можете проверить, для каких предметов есть записи за каждый год. Вы можете сделать это, проверив, равно ли количество различных лет для каждого элемента общему количеству лет (используя COUNT DISTINCT
):
number_years = params[:end_year].to_i - params[:start_year].to_i + 1
@sale_averages = Sale.joins(:shops, :items)
.select('items.name, AVG(sale.price) as price')
.where("EXTRACT(year from season_year) BETWEEN #{params[:start_year]} AND #{params[:end_year]}")
.where('shops.name': params[:select_shop])
.group('items.name')
.having("(COUNT(DISTINCT(EXTRACT(year from season_year))) = #{number_years})")
Я также использовал BETWEEN
вместо <
и >
. Я думаю, что вы хотите сгруппировать по названию товара, а не по магазину (как это было в исходном запросе).