【问题标题】:which one have I to choose between "union" and "case"?我应该在“工会”和“案例”之间选择哪一个?
【发布时间】:2013-09-25 04:42:16
【问题描述】:

我有一个表列表(即 productsA、productsB、productsN...),如果我想选择其中的前 10 个有序 cmets,这些表中的每个产品都可能有注释(存储在 cmets 表中)是最好的解决方案(就性能和速度而言)?

使用联合:

http://www.sqlfiddle.com/#!3/bc382/1

select TOP 10 comment_product, product_name, comment_date FROM (
   select comment_product, product_name, comment_date from comments inner join productsA on product_id = id_product WHERE product_type = 'A' 
UNION
   select comment_product, product_name, comment_date from comments inner join productsB on product_id = id_product WHERE product_type = 'B' 
UNION
   select comment_product, product_name, comment_date from comments inner join productsC on product_id = id_product WHERE product_type = 'C' 
) as temp ORDER BY comment_date DESC

使用案例:

http://www.sqlfiddle.com/#!3/bc382/2

select TOP 10 comment_product, comment_date, 
CASE product_type
  when 'A' then (select product_name from productsA as sub where sub.id_product = com.product_id) 
  when 'B' then (select product_name from productsB as sub where sub.id_product = com.product_id) 
  when 'C' then (select product_name from productsC as sub where sub.id_product = com.product_id) 
END
FROM comments as com
ORDER BY comment_date DESC

【问题讨论】:

  • 由于INNER JOINS,我假设采用UNION 方法。但我会改用UNION ALL,因为它们有所有不同的产品类型,所以不可能重复。
  • "UNION" 组合了单个结果集,这是您在本例中所需要的。 “CASE”涉及数据转换,这里不是你需要的;所以使用“UNION”

标签: sql sql-server select case union


【解决方案1】:

我建议您既不需要UNION 也不需要CASE 并且可以多次JOIN 到cmets:

SELECT TOP 10 
            comment_product
          , COALESCE(a.product_name,b.product_name,c.product_name) AS product_name
          , comment_date 
FROM comments z
LEFT JOIN productsA a
    ON z.product_id = a.id_product  AND z.product_type = 'A' 
LEFT JOIN productsB b
    ON z.product_id = b.id_product  AND z.product_type = 'B' 
LEFT JOIN productsC c
    ON z.product_id = c.id_product  AND z.product_type = 'C' 
WHERE COALESCE(a.id_product,b.id_product,c.id_product) IS NOT NULL
ORDER BY z.comment_dateDESCC

【讨论】:

  • 这永远不会返回任何东西
  • 这会抱怨模棱两可的product_name
【解决方案2】:

第二个查询很可能会在 comment_date 上使用索引扫描,并在产品表上使用嵌套循环,即。 e.最多 10 次逻辑搜索加上从 comments 读取 10 条记录所需的一切

第一个查询很可能会使用索引扫描并对每个查询进行排序,然后对它们的结果进行MERGE UNION

如果您在所有产品表中对comment_dateid_product 都有索引,则第二次查询会快得多。

【讨论】:

    【解决方案3】:

    尽管我不喜欢它,但似乎使用 CASE 会更快。任何SELECT TOP N 都会产生N 个子查询。如果您在所有 3 个产品表中都有 id_product 索引,则应该足够快。

    UNION 解决方案将触发 3 个完整的查询,即 union、sort 和 top。

    【讨论】:

      【解决方案4】:

      我认为是这个。 INNER JOIN 比 UNION 和嵌套查询更快。

      这是SqlFiddle 上的演示。

      SELECT TOP 10 comment_product, comment_date, 
      case when product_type = 'A' then a.product_name 
      when product_type = 'B' then b.product_name 
      when product_type = 'C' then c.product_name 
      else '' end
      FROM comments INNER JOIN productsA a ON product_id = a.id_product  
      INNER JOIN productsB b ON product_id = b.id_product   
      INNER JOIN productsC c ON product_id = c.id_product   
      ORDER BY comment_date DESC
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-06
        • 1970-01-01
        • 2012-11-11
        • 2010-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多