views:

72

answers:

3

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.StartOrEnd = 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?

+2  A: 

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
Martin Smith
Nice. Very elegant. Took me a minute or two to figure out how it works, but I like it.
Bill
Thanks Martin, it did exactly what I wanted it to. Everything working ok, thanks to you.
Hallaghan
+1  A: 

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
Bill
+1  A: 

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
OMG Ponies