July 8, 2011 at 11:58 am
ColdCoffe... almost there, but does not work for example GroupID 5.
CREATE TABLE #MyCodes
(
MyNo int,
GroupID varchar(100),
Code varchar(6),
MyType varchar (15)
)
INSERT INTO #MyCodes VALUES (1, 3, 10, 'Red')
INSERT INTO #MyCodes VALUES (2, 3, 11, 'Red')
INSERT INTO #MyCodes VALUES (3, 3, 11, 'Red')
INSERT INTO #MyCodes VALUES (4, 3, 15, 'Blue')
INSERT INTO #MyCodes VALUES (5, 4, 10, 'Red')
INSERT INTO #MyCodes VALUES (6, 4, 11, 'Red')
INSERT INTO #MyCodes VALUES (7, 4, 15, 'Blue')
INSERT INTO #MyCodes VALUES (8, 4, 11, 'Blue')
INSERT INTO #MyCodes VALUES (9,5,11,'Red')
INSERT INTO #MyCodes VALUES (10,5,13,'Red')
INSERT INTO #MyCodes VALUES (11,5,11,'Brown')
INSERT INTO #MyCodes VALUES (12,5,10,'Red')
INSERT INTO #MyCodes VALUES (13,5,11,'Red')
INSERT INTO #MyCodes VALUES (14,5,12,'Blue')
INSERT INTO #MyCodes VALUES (15,5,10,'Brown')
July 8, 2011 at 12:06 pm
Okay... so we want to see any group with two or more types that have two or more rows per type.
Now tell us again how codes fit into that. I assume that we are still doing our counts within a single group ID. But do we just eliminate codes that have only a single row within the group, or do we eliminate groups that don't have at least two sets of codes with a count of two or more?
Hi Dixie,We need to eliminate groups that don't have at least two sets of types. We need codes but we do not need to do anything with them because they can be anything. We do not have a pattern with them.
July 8, 2011 at 12:57 pm
So this original requirement is off the table now?
where count of Code >=2 group by GroupID
__________________________________________________
Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills
July 8, 2011 at 1:20 pm
Yes, I am thinking to work on one step at a time.
Right now, I am in urgent need to get 2 or more same instances of the Type by the GroupID as per sample data.
Once I have the Type working, then I will worry about the code.
Thank you for your help!
July 8, 2011 at 1:35 pm
The code below will return only rows 5,6,7,8 from the sample table.
; with SampleTable AS
(
SELECT *
FROM
( VALUES
(1, 3, 10, 'Red')
,(2, 3, 11, 'Red')
,(3, 3, 11, 'Red')
,(4, 3, 15, 'Blue')
,(5, 4, 10, 'Red')
,(6, 4, 11, 'Red')
,(7, 4, 15, 'Blue')
,(8, 4, 11, 'Blue')
,(9, 4, 99, 'Green') -- added
) A ( rowNo , groupID, code, type_)
)
-- significant code starts here
-- first identify all types that have two or more rows within a group
,cte1 as (select groupID,type_ from SampleTable group by groupID,type_ having COUNT(*) >= 2)
-- include only rows that meet the criteria from cte1 (join)
-- AND belong to a group that has at least two rows in cte1 (where)
select t.*
from cte1 c
join SampleTable t on c.groupID = t.groupID and c.type_ = t.type_
where t.groupID in (select groupID from cte1 group by groupID having COUNT(*) >=2)
order by rowNo
__________________________________________________
Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills
July 8, 2011 at 7:31 pm
Hi Dixie,
Yes, this is working, and thank you for the explanation.
It makes sence. I really appreciate your help on this one!
John
July 9, 2011 at 11:05 pm
Also:
CREATE TABLE #MyCodes
(
MyNoINTEGER NOT NULL,
GroupIDVARCHAR(100) NOT NULL,
CodeVARCHAR(6) NOT NULL,
MyTypeVARCHAR(15) NOT NULL,
PRIMARY KEY (GroupID, MyType, MyNo)
);
INSERT INTO #MyCodes VALUES (1, 3, 10, 'Red')
INSERT INTO #MyCodes VALUES (2, 3, 11, 'Red')
INSERT INTO #MyCodes VALUES (3, 3, 11, 'Red')
INSERT INTO #MyCodes VALUES (4, 3, 15, 'Blue')
INSERT INTO #MyCodes VALUES (5, 4, 10, 'Red')
INSERT INTO #MyCodes VALUES (6, 4, 11, 'Red')
INSERT INTO #MyCodes VALUES (7, 4, 15, 'Blue')
INSERT INTO #MyCodes VALUES (8, 4, 11, 'Blue')
INSERT INTO #MyCodes VALUES (9,5,11,'Red')
INSERT INTO #MyCodes VALUES (10,5,13,'Red')
INSERT INTO #MyCodes VALUES (11,5,11,'Brown')
INSERT INTO #MyCodes VALUES (12,5,10,'Red')
INSERT INTO #MyCodes VALUES (13,5,11,'Red')
INSERT INTO #MyCodes VALUES (14,5,12,'Blue')
INSERT INTO #MyCodes VALUES (15,5,10,'Brown')
SELECT *
FROM #MyCodes AS mc
WHERE EXISTS
(
SELECT 1
FROM
(
SELECT 1
FROM #MyCodes AS mc2
WHERE mc2.GroupID = mc.GroupID
GROUP BY mc2.MyType
HAVING COUNT_BIG(*) >= 2
) AS G (g)
HAVING COUNT_BIG(*) >= 2
);
July 9, 2011 at 11:23 pm
With a single scan of the source table:
SELECT
y.MyNo,
y.GroupID,
y.Code,
y.MyType
FROM
(
SELECT
*,
distinct_types =
MAX(x.type_rank) OVER (
PARTITION BY x.GroupID),
has_2_items =
COUNT(CASE WHEN x.rn = 2 THEN 1 END) OVER (
PARTITION BY x.GroupID)
FROM
(
SELECT
*,
rn =
ROW_NUMBER() OVER (
PARTITION BY mc.GroupID, mc.MyType
ORDER BY mc.GroupID, mc.MyType),
type_rank =
DENSE_RANK() OVER (
PARTITION BY mc.GroupID
ORDER BY mc.MyType)
FROM #MyCodes AS mc
) AS x
) AS y
WHERE
y.distinct_types >= 2
AND y.has_2_items >= 2;
edit: to incorporate Bob's fix
July 10, 2011 at 12:16 pm
Paul, I tried your code against the data from my example and no rows were returned. I think the proper WHERE clause should be
WHERE y.xr3 = 2 --- denotes at least two types within a group
AND y.xr2 = 1; --- denotes at least two rows within a group and type
I like the idea of using the windowed functions to make only one pass through the primary table, though.
__________________________________________________
Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills
July 10, 2011 at 12:22 pm
The Dixie Flatline (7/10/2011)
Paul, I tried your code against the data from my example and no rows were returned. I think the proper WHERE clause should be
WHERE y.xr3 = 2 --- denotes at least two types within a group
AND y.xr2 = 1; --- denotes at least two rows within a group and type
I like the idea of using the windowed functions to make only one pass through the primary table, though.
Ah, thanks for that! Updated the post with the correction. I can't help feeling there's a more natural (or compact) way to express the logic using the common sub-expression spools...perhaps I'll have another go at it later. For now, I think the EXISTS query is my favourite, from a maintainability point of view, if nothing else!
July 10, 2011 at 12:28 pm
Please do check again ... I changed my data slightly and am seeing unexpected results with the new WHERE clause. But you are definitely on the right track.
Having rechecked, this looks to be working. The xr3 test needed to be GTE, not just equals.
WHERE y.xr3 >= 2 --- denotes at least two types within a group
AND y.xr2 = 1; --- denotes at least two rows within a group and type
__________________________________________________
Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills
July 10, 2011 at 1:19 pm
Hi Bob,
While you were checking that, I changed the code a bit to make more sense (to me). Does my edited version work correctly with your data?
July 10, 2011 at 1:31 pm
Yes, it does.
__________________________________________________
Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills
July 10, 2011 at 2:18 pm
The Dixie Flatline (7/10/2011)
Yes, it does.
Awesome. All we need now is Jeff Moden to build us a million-row test table to see whether all the effort to get a single-scan plan was worthwhile! I suspect not 😀
Thanks for finding that error, Bob.
July 10, 2011 at 5:49 pm
I may have to set up a test tonight. I'm curious about how the sorts play out as the volume ramps up.
__________________________________________________
Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills
Viewing 15 posts - 16 through 30 (of 33 total)
You must be logged in to reply to this topic. Login to reply