Sql 计算并排序每个推荐人的推荐数量

Sql 计算并排序每个推荐人的推荐数量,sql,ruby-on-rails,ruby,Sql,Ruby On Rails,Ruby,首先,我要说我是rails和开发的新手 概述 我有一个简单的转介系统,我想计算每个订阅者转介他人的次数,然后根据转介次数将所有订阅者按降序排列 详细信息 这是我的订阅者表: | id | email | referred_by | referenced\u by包含转介订户的订户id 我想要的是一个方法/查询,它循环遍历表中的每个订阅者,并且: 统计其id出现在所引用的列中的次数 按用户拥有的转介总数订购订户 我是按照下面的思路思考的,但我的部分问题是,我不知道在哪里以及如何在代码库之外测试方

首先,我要说我是rails和开发的新手

概述

我有一个简单的转介系统,我想计算每个订阅者转介他人的次数,然后根据转介次数将所有订阅者按降序排列

详细信息

这是我的
订阅者
表:

| id | email | referred_by |
referenced\u by
包含转介订户的
订户id

我想要的是一个方法/查询,它循环遍历表中的每个订阅者,并且:

  • 统计其id出现在
  • 所引用的
    列中的次数
    
  • 按用户拥有的转介总数订购订户
  • 我是按照下面的思路思考的,但我的部分问题是,我不知道在哪里以及如何在代码库之外测试方法和查询,所以我不知道如何测试。我假设是在控制台中,但我不知道如何在那里执行多部分方法或查询

    Subscriber.all.each do |referrer|
      Subscriber.all.each do |subscriber|
        if referrer.id == subscriber.referred_by
          referrals += 1
        else
          next
        end
      end
    end
    # Then order descending
    

    这是一项最好留给您的数据库完成的任务,它针对这些任务进行了各种优化

    # Fetch subs who have referred others, ordered by number of referrals
    referrers = Subscriber.group('referrer_id').order('count(referrer_id) desc')
    
    # Select number of referrals alongside referrer data
    referrers = referrers.select('count(referrer_id) as referral_count').select('*')
    
    # Example of using the data:
    referrers.each do |referrer|
      puts "#{referrer.name} referred #{referrer.referral_count} others"
    end
    
    对于一个小的数据集,这就足够了,但您可能希望在
    限制
    ,甚至在
    的情况下设置一个最低的推荐数量(即,仅显示至少有一个推荐的用户)

    通常我也会在这里转换字符串,以便更好地使用Arel,但这会使解决方案复杂化,使其更难摸索,所以我没有这样做。下次再做作业


    注意:我在这里使用了稍微不同的术语/列,使这个示例更容易理解和遵循。确保不要盲目复制粘贴。:)

    我建议将此作为一个sqlstatement,让数据库为您完成工作,而不是循环。SQLServer在这方面要熟练得多

    select referred_by, 
       (select email 
          from subscribers sub 
          where id = subscribers.referred_by) as email,
       count(referred_by) as referred
    from subscribers 
    group by referred_by
    order by count(referred_by) desc
    
    这将作为存储过程存在于数据库中,然后我将从应用程序调用它。它不是rubyesq,但它把工作放在了它该做的地方

    Select A.id
          ,A.email
          ,case when B.referrals is null then 0 else  B.referrals end as referrals
     From YourTable A
     Left Join ( 
            Select referred_by,count(*) as referrals
             From  YourTable 
             Where referred_by is not null
             Group By referred_by
          ) B 
        On A.id = B.referred_by
     Order By B.referrals Desc,A.email
    
    你会退回这样的东西吗

    id  email               referrals 
    4   email_4@mail.com    3
    1   email_1@mail.com    2
    2   email_2@mail.com    0
    3   email_3@mail.com    0
    
    编辑


    如果要排除非引用(零计数),请将Left Join更改为internal Join

    另一种方法是对“所属对象”关联使用rails:counter\u cache选项。在您的表中添加一个名为“referrals\u count”(或您更喜欢的内容)的列,该列将记录他们引用的所有订阅者的计数。我认为您还需要将“refered_by”列更改为“refered_by_id”,以便正确设置关联。您的订户型号如下所示:

    class Subscriber < ApplicationRecord
      belongs_to :referred_by, class_name: "Subscriber", counter_cache: :referrals_count
    end
    
    您可以在此处获得有关Rails计数器缓存的更多信息:


    我更喜欢这样做,这样我就不必编写冗长复杂的sql查询。

    谢谢。我通读了文档,但我不完全确定我是否理解这是如何工作的。两个问题:1)我是否需要在我的订户控制器中执行其他操作来说明或保存
    推荐\u count
    ?该帖子未按原样处理。2) 为什么“refered_by”需要“refered_by_id”?1)通过将
    计数器\u缓存::refererals_count
    添加到
    refered_id
    的归属关联中,
    refered_count
    自动更新。因此,在向订阅者添加
    references\u count
    的迁移过程中,请确保为其指定一种整数类型和默认值0:
    add\u列:订阅者,:references\u count,:integer,默认值:0
    。2)您需要将
    referenced\u by
    更改为
    referenced\u by\u id
    ,以便正确设置归属关联。Rails希望任何关联列的末尾都有“\u id”,因为它希望列中的数据是该对象的id。在这种情况下,是订阅者的id引用了他们。检查一下我发送的链接的“属于”部分,它也在这一部分。ActiveRecord关联是RubyonRails的关键基础之一,因此我绝对建议您阅读我包含的链接,因为它将为您节省大量的代码编写时间。
    @subscribers = Subscriber.order(referrals_count: :desc)