Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 按所有子记录分组_Sql_Sql Server_Group By_Sql Server 2012 - Fatal编程技术网

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
;