Alrigth,所以我不确定这是不是太具体......但我真的不知道如何构建这样的查询,既不是在AR中,也不是在SQL中。所以情况如下:
User
型号。 User
has_many Project
s。反过来,Project
具有以下关联:Project
has_one BasicEvent
Project
had_many AdditionalEvent
s BasicEvent
和AdditionalEvent
类是基于AR模型类的继承而构建的,Event
现在,目标是:在我看来,我需要:
Project
User
个点数
Event
happened_at
属性的所有nil
计数
User
的所有Event
排序,按happened_at
的计数排序,nil
public class Tab3 extends Fragment {
private static RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private static RecyclerView recyclerView;
private static ArrayList<String> reminderMessages;
protected static ArrayList<String> receiverNames;
String senderUID;
private DatabaseReference mDatabase;
//Overriden method onCreateView
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Change R.layout.tab1 in you classes
View v = inflater.inflate(R.layout.tab3, container, false);
//get current user
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
reminderMessages = new ArrayList<>();
receiverNames = new ArrayList<>();
senderUID = user.getUid();
mDatabase = FirebaseDatabase.getInstance().getReference();
Query query = mDatabase.child("reminders").orderByChild("senderUID").equalTo(senderUID);
//Setting size of recycler view as constant
recyclerView = (RecyclerView) v.findViewById(R.id.my_recycler_view);
recyclerView.setHasFixedSize(true);
//Setting Linear Layout
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
//Getting message from database
String message = ds.child("reminderMessage").getValue(String.class);
//Adding database to ArrayList
reminderMessages.add(message);
//Getting ReceiverUID
String rUID = ds.child("receiverUID").getValue(String.class);
//Getting corresponding username of the ReceiverUID
GetName getName = new GetName();
getName.GetName(rUID);
reminderMessages.add(message);
// Log.d("String names", receiverNames.toString());
}
adapter = new DataAdapter(reminderMessages,receiverNames);
recyclerView.setAdapter(adapter);
}
@Override
public void onCancelled(DatabaseError databaseError) {
//Error in Reaching Database
Toast.makeText(getContext(), "Something went Wrong!", Toast.LENGTH_SHORT).show();
}
});
//Returning the layout file after inflating
return v;
}
属性
到目前为止,我做了几次尝试,但并没有真正走得太远...我会感谢任何帮助这个复杂的(至少从我的角度来看)查询。
答案 0 :(得分:0)
您可以从以下代码开始:
# -*- frozen-string-literal: true -*-
class UserStatService
SELECT_CLAUSE = <<~SQL
(SELECT count(1) FROM projects WHERE user_id=users.id) AS projects_count,
(SELECT count(1) FROM events WHERE (happened_at IS NULL)
AND (project_id IN (SELECT id FROM projects WHERE user_id=users.id)
) AS events_count,
users.*
SQL
def call
User
.select( SELECT_CLAUSE )
.order( 'events_count' )
end
end
结果集中的每个User
实例都有projects_count
和events_count
个属性。
还建议使用任何类型的缓存(counter_cache
或手工制作)。因为预计查询不会很快。
答案 1 :(得分:0)
假设basic_events
和additional_events
基本上具有相同的列,则此问题的一个很好的解决方案是将您的数据库/应用更改为使用single table inheritance。
假设您正在使用Rails 5.x,您的模型将如下所示:
class User < ApplicationRecord
has_many :projects
has_many :basic_events, through: :projects
has_many :additional_events, through: :projects
end
class Project < ApplicationRecord
belongs_to :user
has_one :basic_event
has_many :additional_events
end
class Event < ApplicationRecord
belongs_to :project
end
class BasicEvent < Event
belongs_to :project
end
class AdditionalEvent < Event
belongs_to :project
end
这样,只有三个表涉及users
,projects
和events
。您的events
表格会有一个:type
列,您可以在其中指定basic
或additional
。
您的疑问:
访问每个用户的所有项目计数
User
.select("users.*, count(projects.id) AS projects_count")
.joins(:projects)
.group('users.id')
.order('projects_count DESC')
使用select这样可以访问此活动记录关系中返回的每个User对象的:projects_count
方法,因此如果您将此查询分配给名为users_with_projects_count
的变量,则可以{{1它将返回与该用户关联的项目数。
访问所有事件计数,其中的events_at属性为nil
users_with_projects_count.first.projects_count
您可以像上一个示例中User
.select("users.*, count(events.id) AS events_count")
.joins(:events)
.where('events.happened_at IS NULL')
.group('users.id')
那样访问:events_count
。
让所有用户按事件计数排序,其中happen_at属性为nil
:projects_count
您使用与上一个示例相同的查询,只需添加User
.select("users.*, count(events.id) AS events_count")
.joins(:events)
.where('events.happened_at IS NULL')
.group('users.id')
.order('events_count DESC')
。
答案 2 :(得分:0)
每位用户的项目数:Project.group(:user_id).count
事件计数,happened_at
中的nil
属性:Event.where(happened_at: nil).count
根据事件计数,用户按happened_at
中的nil
属性进行排序:这是最棘手的,但也不是特别困难:
User.
select("users.*, (SELECT COUNT(*) FROM events WHERE user_id = users.id AND happened_at IS NULL) AS unhappened_events_count").
order("unhappened_events_count DESC")
这不是一个特别有效的查询,但它应该可以很好地完成数千条记录的工作 - 特别是如果你在user_id
和happened_at
中设置索引events
表