【问题标题】:Alternative for sub-query in SQL?SQL中子查询的替代方案?
【发布时间】:2019-02-27 12:23:41
【问题描述】:

我的查询应该返回几个列结果。还有一个要求,我必须为其中一列应用额外的过滤器。我找到了使用子查询(在主选择中选择)的解决方案,这里是示例:

SELECT 
   recid,
   price,
   receive_date,
   (SELECT deduction FROM Cost WHERE recid = c.recid AND status = 'Y') AS deduction
FROM Cost c
   INNER JOIN cost_types ct
      c.recid = ct.recid
WHERE cost_year = '2018'

上面的查询必须从Cost 表中提取与cost_type 表记录匹配的所有记录,其中cost_year2018。最重要的是,我必须提交deduction,其中statusY。我想知道我可以为这个查询使用什么其他技术?我知道UNION / UNION ALL,但那是更多的代码,似乎是多余的。如果有人有建议或更好的方法来处理这种情况,请告诉我。另外,我想知道这是否更适合存储过程?会推荐吗?

【问题讨论】:

    标签: sql sql-server-2008 subquery


    【解决方案1】:

    JOIN 是正常的方法,如下所示:

    SELECT c.recid, c.price, c.receive_date,
           cd.deduction
    FROM cost c INNER JOIN
         cost_types ct
         ON c.recid = ct.recid LEFT JOIN
         cost cd
         ON cd.recid = c.recid AND cd.status = 'Y'
    WHERE c.cost_year = 2018;
    

    这是猜测列的来源。如果列来自不同的表,请调整限定符。

    你也可以使用窗口函数:

    SELECT c.recid, c.price, c.receive_date,
           SUM(CASE WHEN c.status = 'Y' THEN c.deduction END) OVER (PARTITION BY c.recid) as deduction
    FROM cost c INNER JOIN
         cost_types ct
         ON c.recid = ct.recid 
    WHERE c.cost_year = 2018;
    

    【讨论】:

    • 您的第一个选项将消除我在查询结果中仍需要的记录。我解释说,查询应该在当前结果集的顶部返回过滤statusY 的附加列。
    • @espresso_coffee 。 . .第一个查询不会过滤掉任何行。你显然误解了它。
    • WHERE 子句成本年份正在过滤我通过子查询获得的记录。为了获得正确的记录,我需要从主查询中获取 reci 并结合状态标志应用于子查询。我希望这会有所帮助。
    • @espresso_coffee 。 . .不。您的问题中的查询是否正确?你的问题暗示它是。第一个查询应该返回相同的结果集——尽管有些行可能是重复的(在你的版本中你会得到一个错误)。 where 不会过滤 left join 表中的任何内容。
    • 我明白你在说什么。您添加了 LEFT OUTER JOIN 而不是 subquery。你的方法更好有什么理由吗?性能上有什么区别吗?谢谢!
    【解决方案2】:

    为什么不简单地使用CASE ?:

    SELECT recid, price, receive_date,
          (CASE WHEN status = 'Y' THEN deduction END) AS deduction
    FROM Cost c INNER JOIN 
         cost_types ct
         ON c.recid = ct.recid 
    WHERE cost_year =  2018;
    

    编辑:我怀疑你想要一些东西:

    SELECT recid, price, receive_date, c1.deduction 
    FROM Cost c INNER JOIN 
         cost_types ct
         ON c.recid = ct.recid OUTER APPLY 
         (SELECT TOP (1) c1.*
          FROM  Cost c1
          WHERE c1.recid = c.recid AND c1.status = 'Y'
          ORDER BY ?? -- Use ordering column based on you want deduction 
         ) c1;
    WHERE cost_year =  2018;
    

    【讨论】:

    • 我得到了第一行的NULLdeduction 值。我认为recid 必须应用,因为INNER JOIN cost_types 只返回2 条记录。 cost_type 有 4 条记录,但 cost_year 正在过滤,查询仅返回 2 条。无论cost_year 如何,我都需要查看并仅获取状态为 Y 的那些记录。这有意义吗?
    猜你喜欢
    • 2015-08-23
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 1970-01-01
    相关资源
    最近更新 更多