Home > Enterprise >  Subquery result in the WHERE Clause
Subquery result in the WHERE Clause

Time:09-01

I'd like to run a sql like this:

SELECT *,
       (SELECT COUNT(*)FROM ExpandQa WHERE ExpandQa.questionId = id) AS qaCount
FROM Question
WHERE (actId = 9)
  AND (flowState = 40)
  AND (((type = 0
     AND qaCount BETWEEN 1 AND 29)
     OR (type <> 0
     AND qaCount BETWEEN 1 AND 19)))
ORDER BY id DESC;

The result is --> invalid column name 'qaCount'。 My db is SQL Server.

I can fix the problem like this

SELECT *,
       (SELECT COUNT(*)FROM ExpandQa WHERE ExpandQa.questionId = id) AS qaCount
FROM Question
WHERE (actId = 9)
  AND (flowState = 40)
  AND (((type = 0
     AND (SELECT COUNT(*)FROM ExpandQa WHERE ExpandQa.questionId = id) BETWEEN 1 AND 29)
     OR (type <> 0
     AND (SELECT COUNT(*)FROM ExpandQa WHERE ExpandQa.questionId = id) BETWEEN 1 AND 19)))
ORDER BY id DESC;

But I'm afraid that it will be slower. "qaCount" is used three times. I don't hope "(SELECT COUNT(*) FROM ExpandQa WHERE ExpandQa.questionId=id)" is written three times.

Is there a good way to do that?

CodePudding user response:

One possible way to introduce computed data is a lateral join (APPLY)

SELECT *, cnt.qaCount
FROM Question q
CROSS APPLY (
  SELECT COUNT(*) AS qaCount
  FROM ExpandQa e
  WHERE e.questionId = q.id
) cnt
WHERE (actId = 9)
  AND (flowState = 40)
  AND (((type = 0
     AND cnt.qaCount BETWEEN 1 AND 29)
     OR (type <> 0
     AND cnt.qaCount BETWEEN 1 AND 19)))
ORDER BY id DESC;

CodePudding user response:

Simplify as :

WITH
T AS
(
SELECT *, COUNT(ExpandQa.questionId) OVER(PARTITION BY id) AS qaCount
FROM   Question
)
SELECT *
FROM   T
WHERE  actId = 9
  AND flowState = 40
  AND (   (type =  0 AND qaCount BETWEEN 1 AND 29)
       OR (type <> 0 AND qaCount BETWEEN 1 AND 19))
ORDER BY id DESC;

Also, this predicate

AND (   (type =  0 AND qaCount BETWEEN 1 AND 29)
       OR (type <> 0 AND qaCount BETWEEN 1 AND 19))

can be optimized with :

AND qaCount BETWEEN 1 AND CASE type WHEN 0 THEN 29 ELSE 19 END
  • Related