【问题标题】:How to limit results of a LEFT JOIN如何限制 LEFT JOIN 的结果
【发布时间】:2010-07-27 23:08:10
【问题描述】:

以两个表为例:tbl_producttbl_transaction
tbl_product 列出产品详细信息,包括名称和 ID,而 tbl_transaction 列出涉及产品的交易,包括日期、产品 ID、客户等.

我需要显示一个网页,其中显示 10 种产品以及每种产品的最近 5 笔交易。到目前为止,没有LEFT JOIN 查询似乎有效,如果mysql 可以允许tx.product_id=ta.product_id 部分,下面的子查询将有效(在'where 子句'中出现Unknown column'ta.product_id'失败:[错误:1054 ])。

SELECT  
ta.product_id,  
ta.product_name,  
tb.transaction_date  
FROM tbl_product ta  
LEFT JOIN (SELECT tx.transaction_date FROM tbl_transaction tx WHERE tx.product_id=ta.product_id LIMIT 5) tb
LIMIT 10

有没有办法实现我需要的列表无需在循环中使用多个查询

编辑:
这正是我需要的 MySQL:

SELECT ta.product_id, ta.product_name, tb.transaction_date ...  
FROM tbl_product ta  
LEFT JOIN tbl_transaction tb ON (tb.product_id=ta.product_id LIMIT 5)  
LIMIT 10

当然这是非法的,但我真的希望不是这样!

【问题讨论】:

  • 您的加入没有“ON”子句?
  • 即使有 ON 子句,它仍然会获取超过 5 个事务。如果我把tx.product_id=ta.product_id去掉,修改成LEFT JOIN (*my limiting sql*) tb ON tb.product_id=ta.product_id,还是不是我想要的~
  • 你的事务表tbl_transaction有id吗?
  • @gnarf 是的,有一个 transaction_id 列

标签: mysql sql subquery left-join mysql-error-1054


【解决方案1】:

我找到了使用子查询进行 LEFT JOIN 的方法,排序和限制,它适用于 RDS Amazon,MariaDB v10.2

LEFT JOIN activities last_activity ON last_activity.id = ( 
     SELECT id FROM activities 
     WHERE contester_id = contesters.id AND `type` IN ({$last_activity_types}) 
     ORDER BY id DESC LIMIT 1 
)

使用 GROUPING 和 SORTING 进行 LEFT JOIN 的所有其他方法都不适合我。这个例子是工作异常。

【讨论】:

    【解决方案2】:

    这是排名函数非常有用的地方。不幸的是,MySQL 还不支持它们。相反,您可以尝试以下方法。

    Select ta.product_id, ta.product_name
        , tb.transaction_date
    From tbl_product As ta
        Left Join   (
                    Select tx1.product_id, tx1.transaction_id, tx1.transaction_date
                        , (Select Count(*)
                            From tbl_transaction As tx2
                            Where tx2.product_id = tx1.product_id
                                And tx2.transaction_id < tx1.transaction_id) As [Rank]
                    From tbl_transaction As tx1
                    ) as tb
            On tb.product_id = ta.product_id
                And tb.[rank] <= 4
    Limit 10
    

    【讨论】:

    • 感谢您的回复,托马斯。是的,tbl_transaction 有一个 AUTO_INCREMENT 列作为主键。我尝试了您的建议(虽然我不太了解它),我得到了一份产品清单,但没有任何交易。为什么自加入(在 tbl_transaction [tx >-
    • @eddy edu - 其要点是按产品对交易进行排名。为此,我将事务表与自身进行比较,以找出给定产品早于给定行的事务数。产品的最早行应产生零计数。现在,如果你得到奇怪的结果,我有几个问题。首先,交易日期可以为空吗?二、交易日期可以重复(同一product_id和日期两行)?
    • transaction_date 不能为 NULL。 transaction_date 可以重复(一个产品在给定日期可以有多个交易)。我需要按产品对交易进行排名(以便我可以按产品对交易进行“分组”),我只需要查看日期列是如何出现的。
    • @eddy edu - 好的。我已经更新了我的帖子。我没有寻找 Count(Distinct tx2.Id),而是将其更改为 Count(Distinct tx2.transaction_date)。简而言之,我使用 transaction_date 对交易行进行排名。我通过查找日期较早的其他交易行数来做到这一点。给定产品的最早日期应为零。
    • @eddy edu - 我突然想到您可能会遇到交易日期空白的问题。现在正在研究解决方案。
    【解决方案3】:

    它失败是因为当您在查询周围加上括号并为其赋予别名“tb”时,您已经创建了一个派生表。 您的派生表不知道具有别名“ta”的 tbl_product 表

    尝试在派生表之外使用 ON 或 WHERE,然后使用您提供的别名“tb”引用该表

    编辑:

    “LIMIT”的使用限制了整个查询的结果。 虽然您有“LIMIT 10”,但您真正想要的是 50 行(如果历史记录少于 5 行,则更少),对吗?

    10 个产品,连接到 5 个历史记录,总共返回 50 行。

    在这种情况下,您可以使用单个查询解决方案将产品表连接到具有“LIMIT 10”的派生表中

    如:

    SELECT *
    FROM tbl_product ta
    JOIN (SELECT * FROM tbl_product tz WHERE tz.product_id = ta.product_id LIMIT 10) tc
    LEFT JOIN (SELECT tx.transaction_date FROM tbl_transaction tx 
        WHERE tx.product_id=ta.product_id LIMIT 5) tb
    

    您也可以“进入”并指定前 10 名,例如:

    SELECT *
    FROM tbl_product ta
    LEFT JOIN (SELECT tx.transaction_date FROM tbl_transaction tx 
    WHERE tx.product_id=ta.product_id LIMIT 5) tb 
    WHERE ta.product_id IN 
      (SELECT z.product_id FROM tbl_product z LIMIT 10)
    

    【讨论】:

    • 修改后(删除子查询中的 tbl_product 引用并将其添加到 ON 子句中)查询工作正常,但 LIMIT 似乎仅适用于第一个产品,即我得到一个 10 的列表第一个产品有 5 笔交易,但其他所有产品都没有。
    • 再次回答是因为如果您的派生表。派生表中的“LIMIT”与整个查询中的“LIMIT”无关。一些样本数据怎么样?
    • 编辑了我的答案以便更好地解释
    【解决方案4】:

    编辑:

    如果您想对每种产品实施限制,我会将其分成两个查询。

    首先获取 10 种产品的列表,然后对返回最后 5 笔交易的每种产品运行另一个查询。

    【讨论】:

    • 这个失败并出现一个神秘的错误,只能通过一个 ON 子句来解决。在“修复”之后,结果集仅包含第一个具有 5 个交易的产品 - 其他产品被忽略。
    • 我考虑过这一点,但我确信有一个单一查询的解决方案!必须有!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 2015-01-19
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    相关资源
    最近更新 更多