如何加入表格以获得每个独特项目的第一个或最后一个?

时间:2016-12-03 16:22:48

标签: php mysql join

我有以下MySQL查询,我已经工作了一段时间。我想在list_id语句中为每个in获取一条唯一记录。我正在加入表格并检查lists.ordered表以确定是否需要获取第一个或最后一个订单项。

SELECT lists.ordered, 
       cnt1.* 
FROM   cnt_lists AS cnt1 
       LEFT JOIN lists 
              ON cnt1.list_id = lists.id 
       LEFT JOIN cnt_lists AS cnt2 
              ON ( cnt1.list_id = cnt2.list_id 
                   AND ( ( lists.ordered = 1 
                           AND cnt1.id < cnt2.id ) 
                          OR ( lists.ordered = 0 
                               AND cnt1.id > cnt2.id ) ) ) 
WHERE  cnt2.id IS NULL 
       AND cnt1.list_id IN ( '3176', '3295', '3296' ) 
       AND cnt1.listable_type = 'App\\Models\\Movie';

抓住最后一项是很好的,但是当我尝试抓住第一个订单项时,它实际抓住了第二个项目。

有人有任何建议吗?

示例数据:

id     list_id   listable_id   listable_type      order   created_at            updated_at
2226   3296      7             App\Models\Movie   1       2016-12-02 12:56:29   2016-12-02 15:07:42
2224   3296      1             App\Models\Movie   2       2016-11-29 00:06:57   2016-12-02 15:07:42
2227   3296      9             App\Models\Movie   3       2016-12-02 12:56:35   2016-12-02 12:56:35
2228   3296      54            App\Models\Movie   4       2016-12-02 12:56:39   2016-12-02 12:56:39
2229   3296      40            App\Models\Movie   5       2016-12-02 12:56:43   2016-12-02 12:56:43
2230   3296      65            App\Models\Movie   6       2016-12-02 12:56:47   2016-12-02 12:56:47

在上面的示例中,如果lists.ordered = 0它会抓住行2230,因为它是最高order。如果lists.ordered = 1它会抓住行2226,因为它是最低order。最高的工作正常,但最低的是抓住2224,这是第二低的。

2 个答案:

答案 0 :(得分:2)

不要尝试在单个SQL中执行此操作。相反,编写应用程序代码或存储过程以在“第一个”和“最后一个”之间进行选择。

甚至比这更简单:

SELECT ... FROM ...
    ORDER BY ordered ASC   -- ASC gives #1; DESC gives #6 in the example
    LIMIT 1;

如果输出多行,则可能需要Groupwise max问题。

好的,在一个声明中有一种混乱的方式:

( SELECT 0 AS which, ... ORDER BY ordered ASC  LIMIT 1 )
UNION ALL
( SELECT 1 AS which, ... ORDER BY ordered DESC LIMIT 1 )
HAVING which = (however you pick first vs last);

答案 1 :(得分:1)

您希望找到order列排序的第1行/最后一行,但您是否在id列上进行了排序?在这种情况下,试试这个:

SELECT lists.ordered,
       CNT1。*
来自cnt_lists AS cnt1
        LEFT JOIN列表
               ON cnt1.list_id = lists.id
        LEFT JOIN cnt_lists AS cnt2
              ON(cnt1.list_id = cnt2.list_id
                   AND((lists.ordered = 1
                           AND cnt1.order &lt; cnt2.order
                          或(lists.ordered = 0
                               AND cnt1.order &gt; cnt2.order )))
在哪里cnt2.id IS NULL
       AND cnt1.list_id IN(&#39; 3176&#39;,&#39; 3295&#39;,&#39; 3296&#39;)
       AND cnt1.listable_type =&#39; App \ Models \ Movie&#39 ;;