2

I currently have a table Bugs that looks like this:

    |ID      |Priority  |Created   |Updated   |Status    |Category
    |X123    |Major     |01/01     |01/03     |Open      |A
    |X145    |Normal    |01/01     |01/02     |Closed    |B
    |X678    |Minor     |01/03     |01/03     |Open      |C
    |X763    |Major     |01/02     |01/03     |Closed    |C

All columns are varchar(25) except Created and Updated, which are dates.

I need to create a view with the following format:

    |Date      |Major    |Normal    |Minor     |Category
    |01/01     |4        |3         |4         |A
    |01/01     |3        |5         |2         |B
    |01/01     |2        |4         |7         |C    
    |01/02     |7        |3         |4         |A
    |01/02     |3        |9         |5         |B
    |01/02     |1        |6         |3         |C

Where the numbers under Major, Normal, and Minor are the count of CURRENTLY OPEN bugs of that priority on a given date. By currently open, I mean this: open bugs are active on the interval Created-GETDATE(), closed bugs are active on the interval Created-Updated.

I have a list of all the dates I need through this query:

    WITH D AS
     (
      SELECT Dates AS DateValue
      FROM DatesTable
      WHERE Dates >= '2012-03-23'
        AND Dates <= GETDATE()
     ),

Any ideas of how I might do this? I've played with the idea of a pivot query and grouping, but I've not been able to cover everything I need. Your help is greatly appreciated!


EDIT: The Bugs table with example data

    CREATE TABLE [dbo].[Bugs](
            [ID] [varchar](25) NOT NULL,
            [Priority] [varchar](25) NOT NULL,
            [Updated] [date] NOT NULL,
            [Created] [date] NOT NULL,
            [Status] [varchar](25) NOT NULL,
            [Category] [varchar](25) NOT NULL,
            ) ON [PRIMARY]

    INSERT INTO Bugs VALUES (X123, Major, 01/01/12, 01/03/12, Open, A)
    INSERT INTO Bugs VALUES (X145, Normal, 01/01/12, 01/02/12, Closed, B)
    INSERT INTO Bugs VALUES (X678, Minor, 01/03/12, 01/03/12, Open, C)
    INSERT INTO Bugs VALUES (X763, Major, 01/02/12, 01/03/12, Closed, C )
Rose
  • 363
  • 1
  • 3
  • 13
  • 3
    How about some ddl and sample data? You can post here or use sqlfiddle.com. Would also help a bit if you can explain what you want. I don't see needing a pivot. This looks like basic aggregates to me but hard to tell without more detail. – Sean Lange Jul 23 '14 at 14:09
  • @SeanLange I added an example. I can't post the actual data, but I hope this helps – Rose Jul 23 '14 at 14:16
  • Not asking for real data. But some tables so I don't have to build them would go a long way to making this easier. I will toss something together but it may or may not work because I don't have a way to test it. – Sean Lange Jul 23 '14 at 14:18
  • What is the Date in the view? is it the created date or the updated date or the completed date? It seems that you are pulling the data from the `DatesTable`. You have not provided information on this table. – Jenn Jul 23 '14 at 14:23
  • @Jenn Date is every date between the earliest possible created date and present. There is at least 1 bug open on every date between. – Rose Jul 23 '14 at 14:31
  • @BerlinRose: Is it "at least one bug on every day *in every category*"? Do you want to always display every category regardless of whether there was a bug in that category on that day? – Andriy M Jul 23 '14 at 14:45
  • @BerlinRose in you example data you have updated and created flipped so the updated dates are before the created dates. – SQLChao Jul 23 '14 at 14:50

5 Answers5

1

Something like this might what you are looking for.

select b.Date
    , SUM(case when b.Priority = 'Major' then 1 end) as Major
    , SUM(case when b.Priority = 'Normal' then 1 end) as Normal
    , SUM(case when b.Priority = 'Minor' then 1 end) as Minor
    , b.Category
from Bugs b
group by b.Date, b.Category
order by b.Date
Sean Lange
  • 33,028
  • 3
  • 25
  • 40
  • I don't think the OP has provided the date list CTE for nothing, to be honest. To me, it clearly implies that they want all the dates within that period. – Andriy M Jul 23 '14 at 14:25
  • I like your answer better than mine! – Alireza Jul 23 '14 at 14:25
  • Also, there's no `Date` column in `Bugs`. – Andriy M Jul 23 '14 at 14:26
  • 1
    Right about date. I believe he wants to know the number of bugs open/closed as of each of those dates. So one bug could show up in the count on one date and then not be there the next day. – SQLChao Jul 23 '14 at 14:28
  • All the comments about certain columns missing and that sort of thing is why we need to have ddl and data. I was guessing because this wasn't provided. – Sean Lange Jul 23 '14 at 15:08
  • The original question has been edited and now contains that information. This was not there when I posted my initial response. – Sean Lange Jul 23 '14 at 15:10
1

Rather than using a cte, I have used the query as the bases for what you need. by joining the datestable with your bugs table, we can compare the dates in the bugs table to see if the bug was open on the given date. We know that d.dates must be greater than the created date of the bug. We also need to check the bug status. If the bug is open, then we only want to include the bug up til the updated date. Otherwise, the bug needs to be included up to today since it is still open. The rest is essentially manually pivoting the data to get the values you need.

SELECT d.Dates, sum(case when b.priority = major then 1 else 0 end) as major,
        sum(case when b.priority = normal then 1 else 0 end) as normal,
        sum(case when b.priority = minor then 1 else 0 end) as minor,
        b.category
FROM DatesTable d
    join bugs b
    on d.dates >= b.Created 
    and case when b.status = 'closed' then b.updated else '12-31-9999' end <= d.dates
WHERE d.Dates >= '2012-03-23'
AND d.Dates <= GETDATE()
Group by d.dates,b.category
Jenn
  • 795
  • 1
  • 4
  • 16
1

This is what I tested at last:

SELECT d.Dates as Date, 
    SUM(CASE Priority WHEN 'Major' THEN 1 ELSE 0 END) as Major, 
    SUM(CASE Priority WHEN 'Normal' THEN 1 ELSE 0 END) as Normal, 
    SUM(CASE Priority WHEN 'Minor' THEN 1 ELSE 0 END) as Minor,
    b.Category
    FROM Bugs b
INNER JOIN DatesTable d ON d.Dates >= b.Created 
WHERE (Status = 'Closed' AND d.Dates <= Updated OR Status = 'Open')
    AND d.Dates <= GETDATE() AND d.Dates >= '2012-01-01'
GROUP BY d.Dates, b.Category
ORDER BY d.Dates
Alireza
  • 4,976
  • 1
  • 23
  • 36
0

You can use the following query

SELECT DatesTable.Dates
    , SUM(CASE WHEN bugs.Priority = 'Major' THEN 1 ELSE 0 END) AS Major
    , SUM(CASE WHEN bugs.Priority = 'Normal' THEN 1 ELSE 0 END) AS Normal
    , SUM(CASE WHEN bugs.Priority = 'Minor' THEN 1 ELSE 0 END) AS Minor
    , bugs.Category
FROM DatesTable 
LEFT JOIN Bugs ON DatesTable.Dates = Bugs.Date
    -- You may need to cast this, if the data type do not match
    AND Bugs.Status='Open'

WHERE Dates >= '2012-03-23'
      AND Dates <= GETDATE()   
GROUP BY DatesTable.Dates, bugs.Category
ORDER BY DatesTable.Dates
Kiran Hegde
  • 3,651
  • 1
  • 16
  • 14
0

We can use a nested query to get the data we want to work on, and the parent query to display the end result:

 SELECT CreatedDate AS [Date],
        SUM(Major) AS Major,
        SUM(Normal) AS Normal,
        SUM(Minor) AS Minor,
        Category
   FROM (
         SELECT DATEADD(dd, DATEDIFF(dd, 0, Created), 0) AS CreatedDate,
                CASE WHEN Priority = 'Major' THEN 1 ELSE 0 END AS Major,
                CASE WHEN Priority = 'Normal' THEN 1 ELSE 0 END AS Normal,
                CASE WHEN Priority = 'Minor' THEN 1 ELSE 0 END AS Minor,
                Category
           FROM Bugs
          WHERE Status = 'Open'
        ) AS t
  GROUP BY CreatedDate, Category
  ORDER BY CreatedDate, Category

(Credit for removal of time from a DATETIME goes to this SO question)

The nested query makes it easier to see what data is being operated on, and filters said data as needed.

I've assumed the Date is a DATETIME, so I've removed the time part for the grouping.

See an example in this SQL Fiddle (I only added enough data for the first two entries to match the expected results).

Community
  • 1
  • 1
Kevin Hogg
  • 1,771
  • 25
  • 34