Using a case expression in a where clause
Although I know this isn't very efficient, I need to get this working fast so I try to follow the easiest path, or at least I thought so. I'm trying to get the max data out of an entity and take into consideration only the rows where USER is not null, and in case no rows have USER not set to null, then I will take the null ones into consideration.
The entity's structure is as follows:
- Id int,
- ParentId int,
- Guid varchar,
- EventOn DateTime,
- User int (null)
So, the query is the following one:
select RS.[$Id] RangeSheet,
GRST.EventOn,
RSIS.Id [Status],
RSIS.Name StatusRefex
from RangeSheet RS
left outer join (select RST.ParentId RangeSheet,
MAX(RST.EventOn) EventOn
from RangeSheetTime RST
where RST.[User] is (case RST.[User] when null then null else not null)
group by RST.ParentId) GRST on RS.[$Id]=GRST.RangeSheet
left outer join RangeSheetTime RST on GRST.EventOn=RST.EventOn
and GRST.RangeSheet=RST.ParentId
left outer join RangeSheetItemState RSIS on (case when RST.StartOrEnd = 1 then 1 when RST.StartOr开发者_如何学GoEnd = 0 then 4 else null end) = RSIS.Id
where RS.[$IsDeleted]=0
The case I'm having trouble with is the one inside the view GRST. What could I do to accomplish my requirements?
I'm a bit baffled about what you're doing. Going off your text description though would something like the following help?
;WITH t AS
( SELECT Id ,
ParentId,
Guid ,
EventOn ,
USER ,
RANK() OVER (PARTITION BY ParentId ORDER BY
CASE
WHEN USER IS NULL
THEN 0
ELSE 1
END DESC, EventOn DESC) Rnk
)
SELECT *
FROM t
WHERE Rnk=1
I think you are just going to have to left join in two different Max subqueries.
left join (
select RST.ParentId RangeSheet,
MAX(RST.EventOn) EventOn
from RangeSheetTime RST
where Not RST.[User] is NULL
group by RST.ParentId) max1
This subquery will not return a row if all of the ParentID rows have nulls in the User column.
and
left join (
select RST.ParentId RangeSheet,
MAX(RST.EventOn) EventOn
from RangeSheetTime RST
group by RST.ParentId) max2
Now just select the value you want.
coalesce(max1.EventOn, max2.EventOn) as EventOn
Here's my re-write of your query:
SELECT rs.[$Id] RangeSheet,
grst.eventon,
rsis.id AS [Status],
rsis.name AS StatusRefex
FROM RANGESHEET rs
LEFT JOIN (SELECT rst.ParentId,
rst.EventOn,
RANK() OVER (PARTITION BY rst.parentid
ORDER BY CASE
WHEN rst.user IS NULL THEN 0
ELSE 1
END DESC, rst.eventon DESC) Rnk
FROM RANGESHEETTIME rst) grst ON grst.parentid = rs.[$Id]
AND grst.rnk = 1
LEFT JOIN (SELECT rst.eventon,
rst.parentid,
CASE rst.startorend
WHEN 0 THEN 4
WHEN 1 THEN 1
ELSE NULL
END AS item_state_id
FROM RANGESHEETTIME rst
WHERE rst.startorend IN (0, 1)) x ON x.eventon = GRST.EventOn
AND x.parentid = GRST.RangeSheet
LEFT JOIN RANGESHEETITEMSTATE rsis ON rsis.id = x.item_state_id
精彩评论