【问题标题】:php mysql check if vendor has 3 low consecutive ratingsphp mysql检查供应商是否有3个连续低评级
【发布时间】:2016-08-26 19:48:47
【问题描述】:

在我的软件评分表中,我有 4 个字段。 id 自动递增 rvid 供应商 ID 评级日期 评分实际数值评分

在过去的几个月里,我已经做了很多,但这次我很难过,我无法清楚地知道最好的方法。我想要做的是找出供应商是否有 3 个低“连续”评级。如果他们的最后三个评分小于 3,那么我想标记他们。

我已经玩了几个小时了,所以我想我会问(不是为了答案),但是为了一些路径方向只是为了推动我前进,我在这里陷入了思考。

我已经尝试过 GROUP BY 和几个 ORDER BY 但这些尝试并不顺利,所以我想知道这是否不是 mysql 答案而是 php 答案。换句话说,也许我只需要采取我目前所拥有的,然后通过 usort 等移动到 php 方面并这样做。

到目前为止,我确实选择了 id,起初我认为这是获得最后一个 consective 的最佳方式,但后来我有了一个小突破,如果他们连续 3 个,则 id 无关紧要,所以我把它从查询中删除了。

  $sql = "SELECT `rvid`, `rating` FROM `vendor_ratings_archive` WHERE `rating` <= '3' ORDER BY `rvid` DESC";

给我这个

Array
(
[0] => Array
    (
        [rvid] => 7
        [rating] => 2
    )

[1] => Array
    (
        [rvid] => 5
        [rating] => 1
    )

[2] => Array
    (
        [rvid] => 5
        [rating] => 0
    )

[3] => Array
    (
        [rvid] => 5
        [rating] => 3
    )

)

这只是我扔在田里的样本,这里只有 4 行,而在现场,它将有很多行。但基本上这告诉我这些是表中评分较低的供应商。这就是我被难住的地方。我只能在查询中进行一种排序,这就是为什么我认为我需要接受这个并移动到 php 端来完成它。

我想我需要先用 php 按 rvid 对元素进行排序,然后查看一行中的三个元素是否是同一个供应商 (rvid)。

希望这是有道理的。我的脑子好痛哈哈……

更新 - 这是所有使用 * 的表数据

Array
(
[0] => Array
    (
        [id] => 7
        [rvid] => 7
        [ratedate] => 2016-05-01
        [rating] => 2
    )

[1] => Array
    (
        [id] => 8
        [rvid] => 5
        [ratedate] => 2016-05-01
        [rating] => 1
    )

[2] => Array
    (
        [id] => 6
        [rvid] => 5
        [ratedate] => 2016-05-01
        [rating] => 0
    )

[3] => Array
    (
        [id] => 5
        [rvid] => 5
        [ratedate] => 2016-05-01
        [rating] => 3
    )

)  

【问题讨论】:

    标签: php mysql apache vendor


    【解决方案1】:

    你可以在 SQL 中这样做:

    SET @rvid = -1;
    
    SELECT DISTINCT rvid FROM
    (
      SELECT
        rvid,
    
        @neg := rating<3,  /* 0 or 1 for addition in next line */
        @count := IF(@rvid <> rvid , @neg, @count+@neg) AS `count`, /* set or add */
        @rvid := rvid      /* remember last row */
      FROM
        testdb.venrate
    
      ORDER BY
        rvid, datetime desc
    
    ) subq
    
    WHERE   count>=3
    ;
    

    您将变量设置为不存在的 id。在每个按时间顺序排序的行中,您检查评级是否太低,这会导致 1(太低)或 0(正常)。如果 rvid 不等于最后一个 rvid,则意味着新的供应商部分正在开始。在节的开头设置值 0 或 1,否则添加此值。最后存储当前行的rvid,以便在下一行过程中进行比较。

    上面的代码一直在寻找 3 个连续的低评分(低表示值小于 3)。

    小幅修改检查所有最新的 3 个评分是否等于或小于 3

    SET @rvid = -1;
    
    SELECT DISTINCT
      rvid
    FROM
    (
      SELECT
        rvid,
    
        @high_found := rating>3 OR (@rvid = rvid AND @high_found) unflag,
        @count := IF(@rvid <> rvid , 1, @count+1) AS `count`,
        @rvid := rvid      /* remember last row */
    
      FROM
        testdb.venrate
    
      ORDER BY
        rvid, datetime desc
    
    ) subq
    
    WHERE count=3 AND NOT unflag
    ;
    

    【讨论】:

    • 哇!那里的编码令人印象深刻Q...在我头上的方式,但非常酷而且很简单哈哈:)
    • 我添加了一个简短的解释。
    • 经过进一步测试,它似乎将它们标记为 3 个或更多差评,但不是连续的。我测试了 1 1 6 4 3 的评级,这不是连续的 3 或以下,它仍然被标记。我希望他们在获得良好评价后立即从名单中删除。也许我应该在表格中添加一个连续的字段。然后,当我更新表格时,我可以检查最后一个评级值,然后在新字段中增加该值。一旦他们进行了良好的审查,它就会重置该字段的计数器。然后我可以使用连续字段检查有多少连续。听起来合乎逻辑。
    • 既然您要求一个查询来检查连续的低费率,当然它会标记一个供应商的评级为 1 3 2 2 1 4 1,但不是: 1 3 2 1 3 4 1. 计数随着每个低评级而增长,并在高评级时重置。然后按 count >=3 过滤结果。
    • 是的 :) 所以应该从左到右的最高记录开始。应该标记 132621,因为 132 是最后三个记录,并且它们都是 3 和低于评级。但是,如果它是 136621,那么它不会被标记,因为评级 1 和 3 在捕获框内,但 6 不在。现在,如果他们得到另一个差评,可以说 1136621,那么是的。但只要低收视率不是连续 3 次,就没有标签。
    【解决方案2】:

    这是解决这个谜题的方法。我认为在这里解释它有帮助,亚历克斯也有帮助,因为他让我的大脑使用日期。我首先开始考虑在查询中使用 if 语句,实际上这让我的大脑开箱即用,然后它告诉我该怎么做。

    它并不完美,当然可以使用一些修剪来减少代码,但我理解它并且它似乎有效,所以这对我来说是本课程的标准。

    查询...

     $sql = "SELECT `rvid`, `ratedate`,`rating` FROM `vendor_ratings_archive` WHERE `rating` <= '3' ORDER BY `ratedate`, `rvid`  DESC";
    

    这给了我这个

    Array
    (
    [0] => Array
        (
            [rvid] => 7
            [ratedate] => 2016-05-01
            [rating] => 2
        )
    
    [1] => Array
        (
            [rvid] => 5
            [ratedate] => 2016-05-01
            [rating] => 1
        )
    
    [2] => Array
        (
            [rvid] => 5
            [ratedate] => 2016-05-01
            [rating] => 0
        )
    
    [3] => Array
        (
            [rvid] => 5
            [ratedate] => 2016-05-01
            [rating] => 3
        )
    
     )
    

    请注意供应商 (rvid) 5 是如何组合在一起的,这是一个额外的优势。

    接下来是一个简单的 foreach 来加载一个新数组

         foreach($results as $yield)
         {  
    
          $rvidarray[] = $yield['rvid'];          
    
          }//close foreach
    

    这给了我这个

    数组 ( [0] => 7 [1] => 5 [2] => 5 [3] => 5 )

    然后我们计算数组值以分组 dups

     $rvidcounter = array_count_values($rvidarray);
    

    导致这个

    Array(
    [7] => 1
    [5] => 3
    )
    

    所以现在供应商 7 为 1 个低分,供应商 5 有 3 个低分,因为它们已经按日期排序,所以我知道它是连续的。好吧,无论如何听起来都不错,哈哈”)

    然后我们用另一个 foreach 创建我们的最终数组

         foreach($rvidcounter as $key => $value)
         {    
            //anything 3 or over is your watchlist
    
            if($value > 2)
            {
              $watchlist[] = $key; //rvid number stored
             }      
    
             }//close foreach
    

    这给了我这个

    Array
    (
    [0] => 5
    )
    

    这一切都是在服务功能中完成的。所以最后的交易是这个数组中的每个人都有超过 3 个连续的低评分,然后我只是在我的正常 php 进程文件中使用返回的数组,并通过 id 获取每个供应商的名称并将其传递给 html 并打印出列表.

    完成...

    如果您愿意,请随时对此进行改进。我可能会也可能不会使用它,因为上面的代码对我来说很有意义。从现在起 6 个月后,更复杂的事情可能对我来说没有意义,哈哈,但是看看有人想出什么来缩短这个过程会很有趣。

    非常感谢,祝编码愉快!!!!!!
    戴夫:)

    【讨论】:

      【解决方案3】:

      您可以通过以下方式着手解决这个问题 - 完全使用 SQL:

      • 获取供应商的最后评级。 ORDER BY date DESC,限1。
      • 获取供应商倒数第二个评级。 ORDER BY date DESC,limit 1,OFFSET 1。

      然后编写一个查询,对前两个表进行左连接。您将拥有一个包含三列的数据集:

      • 供应商 ID
      • 最后评分
      • 倒数第二个评分

      然后你可以写一个表达式“如果column1

      您应该能够相对轻松地将其扩展到三列。

      【讨论】:

      • 谢谢亚历克斯,我觉得我有编码障碍,我只是坐在这里,在阴霾中盯着屏幕哈哈。这确实有帮助,谢谢... :)
      • 从办公桌上站起来,至少 10 分钟不要看显示器。喝杯咖啡,伸展一下,不要做任何与代码相关的事情。然后就会变得清晰。
      • 实际上我去了外屋,我得到了答案,哈哈——它真的是 omg :)
      猜你喜欢
      • 2011-06-23
      • 2020-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多