MySQL - 如何先 JOIN 然后在 WHERE 然后 LIMIT OFFSET

问题描述 投票:0回答:2

为简单起见:有这3张桌子

my_tickets

+-----------+---------+
| ticket_id | user_id |
+-----------+---------+
| 186       | 2       |
| 187       | 2       |
| 188       | 2       |
| 253       | 33      |
| 254       | 33      |
| 256       | 33      |
| 261       | 33      |
| 262       | 33      |
| 263       | 33      |
| 1573      | 7       |
| 1597      | 7       |
| 1748      | 7       |
+-----------+---------+

my_users

+----+---------+
| id | name    |
+----+---------+
| 2  | user_2  |
| 7  | user_7  |
| 33 | user_33 |
+----+---------+

my_data

+----+-----------+------------+
| id | ticket_id | data       |
+----+-----------+------------+
| 1  | 186       | data_186_1 |
| 2  | 186       | data_186_2 |
| 3  | 187       | data_187_1 |
| 4  | 253       | data_253_1 |
| 5  | 253       | data_253_2 |
| 6  | 253       | data_253_3 |
| 7  | 254       | data_254_1 |
+----+-----------+------------+

我需要什么:在加入表后获取 3 张票的数据(对象,如数据,而不是行),并且仅适用于 user_id=33。我将使用它进行分页。

Desired output
+-----------------------+---------------------+----------------+---------------+
| my_tickets__ticket_id | my_tickets__user_id | my_users__name | my_data__data |
+-----------------------+---------------------+----------------+---------------+
| 253                   | 33                  | user_33        | data_253_1    |
| 253                   | 33                  | user_33        | data_253_2    |
| 253                   | 33                  | user_33        | data_253_3    |
| 254                   | 33                  | user_33        | data_254_1    |
| 256                   | 33                  | user_33        | NULL          |
+-----------------------+---------------------+----------------+---------------+

请阅读这篇文章-https://dncrews.com/limit-and-offset-can-work-with-join-f03327fa2ad3

步骤:

Step 1: JOIN
my_tickets.user_id <=> my_users.id
my_tickets.ticket_id <=> my_data.ticket_id)

+-----------------------+---------------------+----------------+---------------+
| my_tickets__ticket_id | my_tickets__user_id | my_users__name | my_data__data |
+-----------------------+---------------------+----------------+---------------+
| 186                   | 2                   | user_2         | data_186_1    |
| 186                   | 2                   | user_2         | data_186_2    |
| 187                   | 2                   | user_2         | data_187_1    |
| 188                   | 2                   | user_2         | NULL          |
| 1573                  | 7                   | user_7         | NULL          |
| 1597                  | 7                   | user_7         | NULL          |
| 1748                  | 7                   | user_7         | NULL          |
| 253                   | 33                  | user_33        | data_253_1    |
| 253                   | 33                  | user_33        | data_253_2    |
| 253                   | 33                  | user_33        | data_253_3    |
| 254                   | 33                  | user_33        | data_254_1    |
| 256                   | 33                  | user_33        | NULL          |
| 261                   | 33                  | user_33        | NULL          |
| 262                   | 33                  | user_33        | NULL          |
| 263                   | 33                  | user_33        | NULL          |
+-----------------------+---------------------+----------------+---------------+

Step 2: WHERE (my_tickets.user_id = 33)

+-----------------------+---------------------+----------------+---------------+
| my_tickets__ticket_id | my_tickets__user_id | my_users__name | my_data__data |
+-----------------------+---------------------+----------------+---------------+
| 253                   | 33                  | user_33        | data_253_1    |
| 253                   | 33                  | user_33        | data_253_2    |
| 253                   | 33                  | user_33        | data_253_3    |
| 254                   | 33                  | user_33        | data_254_1    |
| 256                   | 33                  | user_33        | NULL          |
| 261                   | 33                  | user_33        | NULL          |
| 262                   | 33                  | user_33        | NULL          |
| 263                   | 33                  | user_33        | NULL          |
+-----------------------+---------------------+----------------+---------------+

Step 3: LIMIT (limit the result to 3 tickets (object kind))

+-----------------------+---------------------+----------------+---------------+
| my_tickets__ticket_id | my_tickets__user_id | my_users__name | my_data__data |
+-----------------------+---------------------+----------------+---------------+
| 253                   | 33                  | user_33        | data_253_1    |
| 253                   | 33                  | user_33        | data_253_2    |
| 253                   | 33                  | user_33        | data_253_3    |
| 254                   | 33                  | user_33        | data_254_1    |
| 256                   | 33                  | user_33        | NULL          |
+-----------------------+---------------------+----------------+---------------+

我尝试了什么:

Query
我希望这个查询在表连接后输出 3 个结果(如第 3 步)并且仅针对 user_id=33,但输出为空

SELECT * FROM (
    SELECT 
        my_tickets.ticket_id AS my_tickets__ticket_id, my_tickets.user_id AS my_tickets__user_id,
        my_users.name AS my_users__name, my_data.data AS my_data__data
    FROM my_tickets
    
    LEFT JOIN my_users ON my_tickets.user_id=my_users.id 
    LEFT JOIN my_data ON my_tickets.ticket_id=my_data.ticket_id 

    WHERE my_tickets.user_id = 33

) as t1

    WHERE
    
    t1.my_tickets__ticket_id IN (
        SELECT * FROM (
            SELECT ticket_id FROM my_tickets LIMIT 3 OFFSET 0
        ) as t2
    )

OUTPUT: Empty table

更新: 回答柠檬的陈述:我出于某种原因使用子查询使事情过于复杂。我需要使用 LIMIT OFFSET 来对内容进行分页。 MySQL 正在对返回的行数应用 LIMIT,另一方面我需要对类对象数据应用 LIMIT。为什么像数据这样的对象? => 我更新了初始问题中的表格以反映这一点(添加了 my_data 表格) 基于这篇文章 - https://dncrews.com/limit-and-offset-can-work-with-join-f03327fa2ad3

sql mysql join left-join limit
2个回答
2
投票

你似乎把事情复杂化了。你可以在没有子查询的情况下做到这一点:

SELECT t.ticket_id,
       t.user_id,
       u.name
FROM       mytickets t
INNER JOIN myusers u ON t.user_id = u.id
WHERE user_id = 33
LIMIT 3

这保持正确的结果,因为以下按给定顺序激活:

  1. FROM
    条款
  2. WHERE
    条款
  3. SELECT
    条款
  4. LIMIT
    条款

在这里你可以得到一个彻底的讨论关于子句之间的执行顺序,或者你可以继续官方文档.

此外,请注意输出不是确定性的,因为您不知道数据在数据库中的存储顺序。确定性地检索三行的唯一方法是使用

ORDER BY
子句,能够在行之间强加顺序并打破潜在的联系。

输出

ticket_id user_id 姓名
253 33 user_33
254 33 user_33
256 33 user_33

在这里查看演示.


更新:如果我想将类对象数据限制在指定数量怎么办?

不要使用

LIMIT
,因为它带来了不必要的复杂性,并且变得非常难以处理。

您可以改为对

DENSE_RANK
排名窗口函数的输出应用过滤。它将为您的对象行的每个记录分配一个标识符,您可以对其应用过滤。

举个例子:

WITH cte AS (
    SELECT t.ticket_id,
           t.user_id,
           u.name,
           DENSE_RANK() OVER(ORDER BY user_id) AS rn
    FROM       mytickets t
    INNER JOIN myusers u ON t.user_id = u.id
)
SELECT * 
FROM cte
WHERE rn <= 3

此查询将允许您从最后三个 user_id 值中选择所有记录,而不仅仅是最后三个记录。


0
投票

首先获得不同的用户和票限制为 3 然后加入

select s.*,md.*,mu.name from
(select distinct user_id,ticket_id from my_tickets mt  where user_id = 33 limit 3) s
left join my_data md on md.ticket_id = s.ticket_id
join my_users mu on mu.id = s.user_id

https://dbfiddle.uk/eloidh90

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.