Sql 按所有子记录分组
如果我有以下数据,其中一条规则可以有多个条件:Sql 按所有子记录分组,sql,sql-server,group-by,sql-server-2012,Sql,Sql Server,Group By,Sql Server 2012,如果我有以下数据,其中一条规则可以有多个条件: ------------------- RuleId CriteriaId ------------------- 1 1 1 2 1 3 2 1 2 2 2 3 3 1 3 2 如何在对规则的所有条件进行分组时获得最小规则ID。换句话说,因为规则1和规则2有完全相同的标准,它们将在一个组中,但因为规则3没有相同的标准,它将在不同的
-------------------
RuleId CriteriaId
-------------------
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
如何在对规则的所有条件进行分组时获得最小规则ID。换句话说,因为规则1和规则2有完全相同的标准,它们将在一个组中,但因为规则3没有相同的标准,它将在不同的组中
我希望得到以下结果:
-------------------
RuleId CriteriaId
-------------------
1 1
1 2
1 3
3 1
3 2
在RuleId上使用MIN直接分组在这里不起作用,因为这样会返回以下信息:
-------------------
RuleId CriteriaId
-------------------
1 1
1 2
1 3
谢谢你的帮助。这里有一种方法。首先,创建具有完全匹配条件的所有规则对的列表。如果每个规则上的数字相同,则条件匹配。当我们计算匹配的数量时,匹配的数量与总数相同 以下查询将查找这些对:
select driver.ruleid1, driver.ruleid2
from (select rc1.ruleid as ruleid1, rc2.ruleid as ruleid2,
rc1.numCriteria as Num1, rc2.numCriteria as Num2
from (select ruleid, COUNT(*) as numCriteria from rc group by ruleid) rc1 join
(select ruleid, COUNT(*) as numCriteria from rc group by ruleid) rc2
on rc1.ruleid <= rc2.ruleid and
rc1.numCriteria = rc2.numCriteria
) driver left outer join
rc rc1
on driver.ruleid1 = rc1.ruleid left outer join
rc rc2
on rc2.ruleid = driver.ruleid2 and
rc1.criteriaId = rc2.criteriaid
group by driver.ruleid1, driver.ruleid2
having max(driver.Num1) = COUNT(distinct rc1.ruleid) and
MAX(driver.Num1) = COUNT(distinct rc2.ruleId)
样本数据
create table rules (RuleId int, CriteriaId int);
insert into rules values
(1 ,1),
(1 ,2),
(1 ,3),
(2 ,1),
(2 ,2),
(2 ,3),
(3 ,1),
(3 ,2);
你的问题
;with flattened as (
select r.ruleid, (select ',' + rtrim(r2.criteriaid)
from rules r2
where r2.RuleId = r.RuleId
order by r2.criteriaid
for xml path(''), type).value('/','varchar(max)') list
from rules r
group by r.ruleid
)
select r3.*
from rules r3
join (
select min(ruleid) min_ruleid
from flattened
group by list) r4 on r4.min_ruleid = r3.ruleid
order by r3.ruleid, r3.CriteriaId;
我不确定这是绝对最好的方法,但它是有效的
CREATE TABLE GroupingTest (RuleId int, CriteriaId int)
INSERT INTO GroupingTest VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 1),
(2, 2),
(2, 3),
(3, 1),
(3, 2)
----------------------------------------------------
WITH MergedGroupingCriteria AS (
SELECT DISTINCT RuleId,
STUFF((SELECT ', ' + CAST(CriteriaId AS varchar)
FROM GroupingTest GT
WHERE GT.RuleId = MergeGroup.RuleId
FOR XML PATH(''),TYPE).value('.','VARCHAR(MAX)')
, 1, 2, '') AS MergedGrouping
FROM GroupingTest MergeGroup )
SELECT MIN(GroupingTest.RuleId), GroupingTest.CriteriaId
FROM GroupingTest
JOIN MergedGroupingCriteria
ON GroupingTest.RuleId = MergedGroupingCriteria.RuleId
GROUP BY MergedGroupingCriteria.MergedGrouping, GroupingTest.CriteriaId
ORDER BY MIN(GroupingTest.RuleId), GroupingTest.CriteriaId
矿山用途:
这里是
我假设这两个字段都是varchar
,结果仍然是串联的
编辑
以下查询没有假设,并提供了正确的结果格式:
SELECT *
FROM Table1
WHERE RuleId IN
(SELECT MIN(list.ruleid) minrule
FROM
(SELECT RuleId,
stuff((
SELECT ', ' + CAST(CriteriaId AS varchar)
FROM Table1 as t1
where t1.RuleId = t2.RuleId
FOR XML PATH('')
), 1, 2, '') Rules
FROM Table1 as t2
GROUP BY RuleId) list
GROUP BY Rules)
ORDER BY RuleId
;
更新了我需要一段时间才能理解这个查询,但是如果两个规则都有3个条件,但其中只有一个条件与这两个规则匹配,会发生什么情况?这个查询会给出一个假阳性,还是能处理这种情况?好吗?@adam0101。
驱动程序表将给出一个“假”阳性。但随后,匹配标准的数量会在每一侧计算。这就是附加联接、groupby
和having
子句的目的。我想知道与@Gordon的答案相比,性能如何。据我估计,速度更快。它是O(N^2),但只有在(ruleid,criteriaid)上有适当的索引时,内部N(字符串concat)才在子集上。它也是100%正确的,因为它比较了集合中的确切条件id,而不是仅仅计数。你是对的。在我们建立了一些索引之后,这要快得多。谢谢
SELECT MIN(list.ruleid) minrule, rules
FROM
(SELECT RuleId,
stuff((
SELECT ', ' + CriteriaId
FROM Table1 as t1
where t1.RuleId = t2.RuleId
FOR XML PATH('')
), 1, 2, '') Rules
FROM Table1 as t2
GROUP BY RuleId) list
GROUP BY Rules
ORDER BY minrule;
SELECT *
FROM Table1
WHERE RuleId IN
(SELECT MIN(list.ruleid) minrule
FROM
(SELECT RuleId,
stuff((
SELECT ', ' + CAST(CriteriaId AS varchar)
FROM Table1 as t1
where t1.RuleId = t2.RuleId
FOR XML PATH('')
), 1, 2, '') Rules
FROM Table1 as t2
GROUP BY RuleId) list
GROUP BY Rules)
ORDER BY RuleId
;