【问题标题】:Multiple similar SELECTs in one statement一条语句中有多个相似的 SELECT
【发布时间】:2019-07-16 10:41:16
【问题描述】:

我在 SQL 中有这些 SELECT 语句: 这个:

SELECT
    *
FROM
    products
WHERE
    product_category = '12'
LIMIT
    3

还有这个:

SELECT
    *
FROM
    products
WHERE
    product_category = '36'
LIMIT
    3

还有这个:

SELECT
    *
FROM
    products
WHERE
    product_id IN ('3178','3181','7403')
LIMIT
    3

如您所见,它们非常相似,我想要有效地运行这 3 个语句,关键是整个结果应该是 9 行长(因为 3x3),首先应该显示来自类别 12 的三个产品,则应显示类别 36 中的后三个产品,最后三个产品应为 ID 为 3178,3181,7403 的产品。

我知道我可以像这样使用UNION

    (SELECT
        *
    FROM
        products
    WHERE
        product_category = '12'
    LIMIT
        3)
UNION
    (SELECT
        *
    FROM
        products
    WHERE
        product_category = '36'
    LIMIT
        3)
UNION
    (SELECT
        *
    FROM
        products
    WHERE
        product_id IN ('3178','3181','7403')
    LIMIT
        3)
LIMIT 9

但我想知道,是否有更有效的方法,因为这些语句大多是副本。

【问题讨论】:

  • 为什么限制为 3?有什么具体原因吗?
  • 请注意,单独使用 UNION 并不能保证您需要的 category=12,然后是 36 等顺序。“UNION 默认情况下会生成一组无序的行” .参考:dev.mysql.com/doc/refman/8.0/en/union.html
  • 您使用的是哪个 MySQL 版本?
  • @James 因为它必须是 3

标签: mysql sql select union


【解决方案1】:

mysql 8.0 或更高版本可以减少一个子查询

select col1,col2,col3 from (SELECT *, row_number() over(partition by product_category  order by product_category) rn
    FROM
        products
    WHERE
        product_category in( 12,36) 
) a where a.rn<=3


union 
  SELECT
        col1,col2,col3
    FROM
        products
    WHERE
        product_id IN ('3178','3181','7403') order by product_id
    LIMIT
        3 

【讨论】:

  • 这并不能保证OP的要求:“首先应该显示来自第12类的三个产品,然后应该显示来自第36类的三个产品,最后三个产品应该是具有ID 3178,3181,7403." .. btw 不是我的 DV
【解决方案2】:

在 MySQL 8+ 中,您可以使用窗口函数:

SELECT p.*
FROM (SELECT p.*,
             ROW_NUMBER() OVER (PARTITION BY product_category, 
                                             product_id IN (3178, 3181, 7403)
                                ORDER BY product_category
                               ) as seqnum
      FROM products p
      WHERE product_category IN (12, 36) OR
            product_id IN (3178, 3181, 7403)
     ) p
WHERE seqnum <= 3
ORDER BY (product_category = 12) DESC,
         (product_category = 36) DESC;

【讨论】:

  • 这并不能保证OP的要求:“首先应该显示来自第12类的三个产品,然后应该显示来自第36类的三个产品,最后三个产品应该是具有ID 3178,3181,7403." .. btw 不是我的 DV
  • @MadhurBhaiya。 . .那是因为 UNION 查询不这样做,并且 OP 声称 UNION 有效。但我添加了适当的ORDER BY
  • 你能帮我吗,在第 3 行 ROW_NUMBER() OVER (PARTITION BY product_category, 我收到错误,缺少右括号。
【解决方案3】:
UNION ALL

UNION 将尝试将相似的记录合并为一个。使用 UNION ALL,将显示所有内容。

【讨论】:

    【解决方案4】:

    也许如果您真的想提高效率,您必须以稍微不同的方式看待它,不要将自己局限于查询,而是考虑更新您的数据库结构。

    例如,您可以在products 表中添加一个新列来处理组订单。

    | product_id | product_category | product_group |
    |------------|------------------|---------------|
    | 3178       |                  | c             |
    |            | 12               | a             |
    |            | 36               | b             |
    | 3181       |                  | c             |
    | 7403       |                  | c             |
    

    并通过简单的查询获得结果:

    SELECT * from products
    WHERE product_group in (a, b, c)
    ORDER BY product_group
    

    根据您将每个组限制为 3 个结果的原因,使用代码来管理您想要返回的条目可能更有意义(因此有一些代码来设置 product_group 字段),不仅仅是表中的前 3 个条目,没有特定的顺序。

    【讨论】:

    • @James 不同意,因为 OP 的问题是“我想知道,是否有更有效的方法”。但要指出的是,这是一个间接的答案。
    猜你喜欢
    • 2016-06-03
    • 2015-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-21
    • 2014-08-19
    • 1970-01-01
    相关资源
    最近更新 更多