php-mysql检查供应商是否有3个低的连续评级


php mysql check if vendor has 3 low consecutive ratings

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

在过去的几个月里,我已经做了很多工作,但这次我被难住了,我无法在脑海中清晰地想象最好的方法。我想做的是找出供应商是否有3个低的"连续"评级。如果他们的最后三个评级是<3然后我想标记它们。

我已经玩了几个小时了,所以我想我会问(不是为了得到答案),但为了找到一些推动我前进的道路方向,我陷入了在这里绕圈思考的困境。

我尝试过GROUP BY和ORDER BY,但这些尝试都不顺利,所以我想知道这是否不是mysql的答案,而是php的答案。换句话说,也许我只需要利用我目前所拥有的,通过usort等转到php方面,然后用这种方式来做。

这是我到目前为止所拥有的,我一开始也选择了id,认为这是获得最后一个结果的最佳方式,但后来我有了一个小突破,如果他们连续有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对元素进行排序,然后看看一行中的三个元素是否是同一个vender(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
    )
)  

这里有一种方法可以完全在SQL:中开始处理这个问题

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

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

  • 供应商id
  • 上次评级
  • 倒数第二的评级

然后你可以写一个表达式,说"如果column1是<3,column2<三,那么这个新列是真的"

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

以下是a解决这个谜题的方法。我认为在这里解释它有帮助,亚历克斯也有帮助,因为他让我的大脑在使用日期。我首先开始考虑在查询中使用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)

然后我们对数组值进行计数,以对重复进行分组

 $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个月后,一些更复杂的东西对我来说可能没有意义。哈哈,但看看有人能想出什么来缩短这个过程会很有趣。

非常感谢和快乐编码
Dave:)

您可以在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
;