Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
SMerrill
Posting Yak Master
206 Posts |
Posted - 2002-11-13 : 17:50:52
|
I am having a problem yielding a result set with zero counts.I am expecting the following result set:Date PatternID K----------- ----------- ---2002-07-01 1 12002-07-01 2 12002-07-01 3 12002-07-02 1 02002-07-02 2 12002-07-02 3 02002-07-03 1 12002-07-03 2 02002-07-03 3 0 Here is my schema:CREATE TABLE [dbo].[History] ( [Date] [datetime] NOT NULL , [PatternID] [int] NOT NULL ) ON [PRIMARY]CREATE TABLE [dbo].[MinimalPatternList] ( [PatternID] [int] NOT NULL ) ON [PRIMARY]ALTER TABLE [dbo].[History] WITH NOCHECK ADD CONSTRAINT [PK_History] PRIMARY KEY CLUSTERED ([Date],[PatternID])ALTER TABLE [dbo].[MinimalPatternList] WITH NOCHECK ADD CONSTRAINT [PK_MinimalPatternList] PRIMARY KEY CLUSTERED ([PatternID])delete from historydelete from minimalpatternlistinsert into History (Date, PatternID) Values ('7/1/2002',1)insert into History (Date, PatternID) Values ('7/1/2002',2)insert into History (Date, PatternID) Values ('7/1/2002',3)insert into History (Date, PatternID) Values ('7/2/2002',2)insert into History (Date, PatternID) Values ('7/3/2002',1)insert into MinimalPatternList (PatternID) Values (1)insert into MinimalPatternList (PatternID) Values (3)GOCREATE VIEW v_CrossJoin AS SELECT History.Date, MinimalPatternList.PatternID, COUNT(*) AS KFROM History CROSS JOIN MinimalPatternListGROUP BY History.Date, MinimalPatternList.PatternIDNo matter what kind of join I write, I cannot get zero counts in my results.Given my level of experience with the relational model, I am embarrased. I find this cross-join idea easier in Access.Thanks for your help,--SMerrillSeattle, WA |
|
|
burbakei
Yak Posting Veteran
80 Posts |
Posted - 2002-11-13 : 20:05:50
|
| you can use the following SELECT in your viewSELECT History.Date, MinimalPatternList.PatternID, COUNT(*) AS KFROM History CROSS JOIN MinimalPatternListGROUP BY History.Date, MinimalPatternList.PatternIDUNION ALLSELECT History.Date, History.PatternID, 0FROM HistoryLEFT OUTER JOIN MinimalPatternList ON History.PatternID = MinimalPatternList.PatternIDWHERE MinimalPatternList.PatternID IS NULLGROUP BY History.Date, History.PatternIDORDER BY History.Datebut you must expect the following result set:Date PatternID K -------------------------------------------- ----------- ----------- 2002-07-01 00:00:00.000 1 32002-07-01 00:00:00.000 3 32002-07-01 00:00:00.000 2 02002-07-02 00:00:00.000 2 02002-07-02 00:00:00.000 3 12002-07-02 00:00:00.000 1 12002-07-03 00:00:00.000 1 12002-07-03 00:00:00.000 3 1 |
 |
|
|
SMerrill
Posting Yak Master
206 Posts |
Posted - 2002-11-18 : 17:22:06
|
| The second half of your union properly answers the question,"List all dates which contain non-required patterns."But this does not answer my question, which is,"List all days that do not contain the required patterns, and list the missing patterns for those dates."Edited by - smerrill on 11/18/2002 17:55:45 |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2002-11-18 : 18:18:30
|
| I consider myself somewhat of a CROSS JOIN expert (I use them and love them!) here is what I think:First, you need a table of all patterns, which you have. You also need a table of all dates:(SELECT DISTINCT Date FROM History) As EachDatewill do the trick.From there, you CROSS JOIN the Patterns table with the EachDate query, giving you all combinations.But, we are not done. Encapsulate the CROSS JOIN in a subquery, and using that subquery you do a LEFT OUTER JOIN to your History table. A NULL value in the History table means you return a 0, otherwise a 1. All of your key data comes from the CROSS JOIN'd subquery.SELECT AllCombos.Date, AllCombos.PatternID, CASE WHEN History.Date is NULL THEN 1 ELSE 0 END as KFROM(SELECT EachDate.Date, P.PatternIDFROM MinimalPatternList PCROSS JOIN (SELECT DISTINCT Date FROM HISTORY) EachDate) AllCombosLEFT OUTER JOIN History ON History.Date = ALlCombos.Date AND History.PAtternID = AllCombos.PAtternIDI call this an (A x B) -> C type report; you do a cross join of table A and B to guarantee you have all values, and then from there do a LEFT OUTER JOIN to your actual data. They key is that all of your sorts and grouping and everything comes from the (A x B) portion, and your numerical results (handling NULL's as zeroes or whatever you want) comes from the C table.Edited by - jsmith8858 on 11/18/2002 18:20:14 |
 |
|
|
SMerrill
Posting Yak Master
206 Posts |
Posted - 2002-11-18 : 18:31:51
|
SQL Team: (JSmith just needs to reverse (his/her) 1 and 0 in the CASE statement, and it works. I think it is more elegant than mine, and I'm inspired by it. My view comes up with two more records than (his/hers), but still doesn't come up with all of them.)Thanks for your help one and all ...Here is the answer I arrived at just before JSmith replied. I got this one myself, even though it nearly drove SQL nuts! :SELECT Date, PatternID, COUNT(*) AS [Count] FROM HistoryGROUP BY Date, PatternIDUNION ALLSELECT AllReq.Date, AllReq.PatternID, 0 AS [Count]FROM (SELECT AllDates.Date, MinimalPatternList.PatternID FROM (SELECT DISTINCT Date FROM History) AllDates CROSS JOIN MinimalPatternList ) AllRequirementsLEFT OUTER JOIN History h ON AllRequirements.Date = h.Date AND AllRequirements.PatternID = h.PatternIDWHERE (h.PatternID IS NULL) The only record that is missing is 7/3 Pattern #2, which is not really necessary, as it is not required. (JSmith's answer leaves out 7/1 #2 and 7/2 #2, which aren't necessary either.)This makes me academically wonder if there is an easier way, but I don't know relational algebra yet.We don't need no steenkin' algebra . . . We've got sub-queries!Thanks for your time, SQL Team! It was fun!--SMerrillSeattle, WAEdited by - smerrill on 11/18/2002 19:07:51 |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2002-11-18 : 19:12:12
|
| I just realized that your MinimalPAttern table doesn't have the #2 ... that's why mine doesn't show it! I read your table defs quickly and thought it contained 1, 2 and 3.In order for a query like this to work, you would need all of the records in at least 1 table. If you can't add #2 to the patterns table, you could alter my query and do it this way:SELECT AllCombos.Date, AllCombos.PatternID, CASE WHEN History.Date is NULL THEN 0 ELSE 1 END as K FROM (SELECT EachDate.Date, P.PatternID FROM (SELECT DISTINCT PAtternID FROM History) P CROSS JOIN (SELECT DISTINCT Date FROM HISTORY) EachDate) AllCombos LEFT OUTER JOIN History ON History.Date = ALlCombos.Date AND History.PAtternID = AllCombos.PAtternIDThat will give you all combinations.Thanks for the nice words. I'm a "he", by the way!(and thanks for pointing out the error in my CASE clause ... oops !)- JeffEdited by - jsmith8858 on 11/18/2002 19:18:24 |
 |
|
|
|
|
|
|
|