如何在 SQL Server 中使用子查询而不是视图

Posted

技术标签:

【中文标题】如何在 SQL Server 中使用子查询而不是视图【英文标题】:How To Use a Sub-Query instead of a View In SQL Server 【发布时间】:2021-04-02 00:16:48 【问题描述】:

我有一个包含许多记录和重复 ID 的表。我正在尝试按每个 ID 分组并显示最新日期的记录。只能显示一个 ID,并且应该是日期最晚的记录。我已经在下面的查询中完成了,我已经将此查询放入 SQL Server 中的视图中:

Pymt_View:

SELECT MAX(CONVERT(datetime, pmt_dt)) AS PymtDate, id_no AS ID, MAX(CONVERT(datetime, due_dt)) 
AS PymtDueDate, pmt_cd
FROM  Payment_Table
WHERE (CONVERT(datetime, due_dt) <= GETDATE()) AND (pmt_cd = '999') AND (amount > 0)
GROUP BY ID, pmt_cd

然后我在新查询中使用此视图来加入原始 Payment_Table 以根据联接中列的匹配来获取我需要的列。我将 View 用作左表,将原始付款表用作右表。

以视图为左表的新查询:

select a.PymtDate, a.[ID], a.PymtDueDate, b.amount, b.pmt_cd, b.batch_no
from Pymt_View a left join Payment_Table b on (a.ID = b.ID) and a.PymtDate = cast(b.pmt_dt as 
datetime) and a.pmt_cd = b.pmt_cd)
order by a.[ID] asc, PymtDate desc, PymtDueDate desc

这会产生我需要的结果。但是,我很好奇如何在一个查询/视图中执行此操作而无需创建 Pymt_View?我尝试使用以下代码对我需要的分组人口进行子查询并将其加入表中以获取我无法通过查询从组中获取的我需要的列。我需要 b.amount、b.pmt_cd、b.batch_no 列,但无法通过 group by 获得它们

select x.*,
from (
   SELECT MAX(CONVERT(datetime, pmt_dt)) AS PymtDate, id_no AS ID, MAX(CONVERT(datetime, due_dt)) 
   AS PymtDueDate, pmt_cd
FROM  Payment_Table
WHERE (CONVERT(datetime, due_dt) <= GETDATE()) AND (pmt_cd = '999') AND (amount > 0)
GROUP BY ID, pmt_cd
) x left join Payment_Table on (a.ID = b.ID) and a.PymtDate = cast(b.pmt_dt as datetime) and a.pmt_cd 
= b.pmt_cd)

这不起作用。最终,如果我能够从 payment_table 获得我需要的人口,而无需使用 pymt_view。然后,我需要将该查询与另一个人口一起加入,因此我必须再次创建一个视图,该视图将在另一个视图中使用。有什么办法可以避免创建视图并将它们用作表格?我希望所有这些都在一个可以放入视图的查询中。无需创建更多要在视图中使用的视图。我希望只在一个视图中执行此操作。

感谢您的帮助。

【问题讨论】:

您想按pmt_dtdue_dt 对哪个日期进行排序?还有Bad Habits to Kick : Using table aliases like (a, b, c) or (t1, t2, t3) 你为什么这么随意地使用convert(datetime,...)?列日期时间与否?如果存储日期/时间的源列确实是字符串,那么它不应该是。尝试您的查询而不转换为日期时间 这行得通。谢谢! 【参考方案1】:

您可以使用行编号解决方案非常有效地做到这一点:

SELECT
    CONVERT(datetime, pmt_dt) PymtDate,
    p.[ID],
    CONVERT(datetime, due_dt) PymtDueDate,
    p.amount,
    p.pmt_cd,
    p.batch_no
from (
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY ID, pmt_cd ORDER BY CONVERT(datetime, pmt_dt) DESC) AS rn
    FROM Payment_Table
    WHERE (CONVERT(datetime, due_dt) <= GETDATE()) AND (pmt_cd = '999') AND (amount > 0)
) p
WHERE rn = 1
order by a.[ID] asc, PymtDate desc, PymtDueDate desc

【讨论】:

以上是关于如何在 SQL Server 中使用子查询而不是视图的主要内容,如果未能解决你的问题,请参考以下文章

如果嵌套查询在 SQL Server 中是不是有结果,如何返回是或否?

如何在子查询 SQL Server 中选择多个项目

在SQL Server中为啥不建议使用Not In子查询

使用 SQL Server 将子查询结果重用于其他计算

如何在 SQL Server 2005 中回滚 UPDATE 查询?

如何在 SQL Server 中的 UPDATE 查询的子查询中引用表变量