【问题标题】:Using subquery's alias in a WHERE statement在 WHERE 语句中使用子查询的别名
【发布时间】:2012-07-26 21:25:16
【问题描述】:

我正在尝试使用在 SELECT 中创建的别名,但在 WHERE 语句中。我知道它不起作用,我只是在另一个 SO 问题中阅读了原因。

但我的问题是:在不重复子查询的情况下,我应该采取什么其他解决方案来完成这项工作?

SELECT p.PatientID, p.PatientType, p.AccountNumber, p.FirstName + ' ' + p.LastName PatientFullName, p.CreatedDate,
DATEDIFF(hour, p.CreatedDate, GETDATE()) TotalTime,
(SELECT AVG(BGValue) FROM BloodGlucose WHERE PatientID = p.PatientID) AvgBG
FROM Patients p
WHERE AvgBG > 60;

我知道这行得通:

SELECT p.PatientID, p.PatientType, p.AccountNumber, p.FirstName + ' ' + p.LastName PatientFullName, p.CreatedDate,
DATEDIFF(hour, p.CreatedDate, GETDATE()) TotalTime,
(SELECT AVG(BGValue) FROM BloodGlucose WHERE PatientID = p.PatientID) AvgBG
FROM Patients p
WHERE (SELECT AVG(BGValue) FROM BloodGlucose WHERE PatientID = p.PatientID) > 60;

但我不想重复那个子查询。而且我很确定它在性能方面不是很明智,所以这就是我在这里寻求更好解决方案的原因。

谢谢!

【问题讨论】:

  • 如果您担心性能,您不应该从编写相关子查询开始!
  • 这就是我最后一句话的原因!我知道这不是性能方面的,我正在寻求另一种解决方案。

标签: sql sql-server sql-server-2008 subquery


【解决方案1】:

尝试使用派生表。

SELECT p.PatientID, p.PatientType, p.AccountNumber, p.FirstName + ' ' + p.LastName PatientFullName, p.CreatedDate, DATEDIFF(hour, p.CreatedDate, GETDATE()) TotalTime, bg.AvgBG 
FROM Patients p 
JOIN (SELECT PatientID, AVG(BGValue) AvgBG   FROM BloodGlucose group by PatientID ) BG
    ON BG.PatientID = p.PatientID 
WHERE AvgBG > 60; 

【讨论】:

  • 派生表在集合中工作,相关子查询逐行工作,这就是我的速度更快的原因。
  • 啊,顺便说一句,以 ON PatientID 开头的行应该是 ON bg.PatientID。
【解决方案2】:

WHERE 子句中的别名只能来自 FROM 子句。这是一种重写查询的方法:

SELECT p.PatientID, p.PatientType, p.AccountNumber,
       p.FirstName + ' ' + p.LastName as PatientFullName, p.CreatedDate,
       DATEDIFF(hour, p.CreatedDate, GETDATE()) TotalTime,
       av.AvgBG
FROM Patients p join
     (SELECT PatientId, AVG(BGValue) as AvgBG
      FROM BloodGlucose
      group by PatientID
     ) av
     on p.PatientId = av.PatientId
WHERE av.AvgBG > 60;

【讨论】:

  • 它给了我:Msg 4104, Level 16, State 1, Line 8 无法绑定多部分标识符“p.PatientID”。 :-/ 感谢您的回复。
  • @RGI 。 . .固定的。那应该是一个分组声明。
【解决方案3】:
SELECT p.PatientID, p.PatientType, p.AccountNumber, p.FirstName + ' ' + p.LastName PatientFullName, p.CreatedDate, DATEDIFF(hour, p.CreatedDate, GETDATE()) TotalTime, bg.AvgBG  
FROM Patients p  
outer apply (SELECT PatientID, AVG(BGValue) AvgBG   
FROM BloodGlucose where PatientID = p.PatientID  
 group by PatientID ) BG 
 WHERE AvgBG > 60; 

这也应该很快就能工作

【讨论】:

    【解决方案4】:
    SELECT p.PatientID, p.PatientType, p.AccountNumber, p.FirstName p.LastName PatientFullName, p.CreatedDate,
    DATEDIFF(hour, p.CreatedDate, GETDATE()) TotalTime, a.AvgBG
    FROM Patients p,
    (SELECT PatientID, AVG(BGValue) AvgBG
      FROM BloodGlucose
    group by PatientID
    having AVG(BGValue) > 60) a
    where p.PatientID = a.PatientID
    

    【讨论】:

    • 你永远不应该推荐使用 SQL 反模式,比如隐式连接。
    • @HLGEM - 为什么?它和你做的工作一样。对?你能解释一下Downvote plz吗?
    • @RGI,我确实解释过,我们不想鼓励糟糕的编码实践,而隐式连接是 20 年前被取代的糟糕的编码实践。如果您尝试使用左连接和内连接,则会出现更多的主题错误,例如意外的交叉连接和不正确的结果,更难维护,而且不太清楚。
    • 我第一次听说“隐式连接”是“反模式”,尤其是“更难维护”。 SQL需要维护?!您会将错误的意外交叉连接部署到生产应用程序中吗?谁会使用 SQL 控制台并意外运行复制粘贴的错误 SQL(未通过版本控制检索,未在 QA 中测试)?没有人。
    【解决方案5】:

    您可以尝试在标准 SQL 中使用 WITH 子句。

    WITH Subquery AS
    (
        Your Code
    )
    

    然后是你的代码

    SELECT ....
    Subquery As sq
    From Patients p
    WHERE(subquery)>60
    

    【讨论】:

      【解决方案6】:

      使用公用表表达式:

      ;WITH CTE (PatientID, PatientType, AccountNumber, PatientFullName, CreatedDate, TotalTime, AvgBG) AS (
          SELECT p.PatientID, p.PatientType, p.AccountNumber, p.FirstName + ' ' + p.LastName PatientFullName, p.CreatedDate,
          DATEDIFF(hour, p.CreatedDate, GETDATE()) TotalTime,
          (SELECT AVG(BGValue) FROM BloodGlucose WHERE PatientID = p.PatientID) AvgBG
          FROM Patients p
      )
      
      SELECT PatientID, PatientType, AccountNumber, PatientFullName, CreatedDate, TotalTime, AvgBG
      FROM CTE
      WHERE AvgBG > 60
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多