SQL Server Using subquery's alias in a WHERE statement

xwbd5t1u  于 2023-05-16  发布在  其他
关注(0)|答案(6)|浏览(158)

I'm trying to use an alias created in a SELECT in a WHERE statement. It doesn't work and I read why in another SO question.

How do I make this work without repeating the subquery?

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;

This works:

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;

But I don't want to repeat that subquery. And I suspect it has poor performance.

gblwokeq

gblwokeq1#

Try using a derived table instead.

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;

Derived tables work in sets and correlated subqueries work row-by-agonizing-row, that is why mine is faster.

mwyxok5s

mwyxok5s2#

The aliases in the WHERE clause can only come from the FROM clause. Here is a way to rewrite your query:

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;
oknwwptz

oknwwptz3#

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;

this should also work pretty quickly

vybvopom

vybvopom4#

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
egdjgwm8

egdjgwm85#

You can try to use WITH clause in standard SQL.

WITH Subquery AS
(
    Your Code
)

And then your code

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

ttvkxqim6#

Use a common table expression:

;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

相关问题