如何统计同一桌子中的交叉?

时间:2017-01-05 06:13:29

标签: sql tsql

我有一张表Categories

|Category|Person|
|--------|------|
|A       |P1    |
|A       |P2    |
|A       |P3    |
|B       |P1    |
|C       |P2    |
|C       |P3    |
|D       |P4    |

我想计算有A的人有B的人数以及有A的人C的人数。所以交叉:

|Category A|Category B|Count|
|----------|----------|-----|
|A         |B         |1    |
|A         |C         |2    |
|A         |D         |0    |
|B         |A         |1    |
|B         |C         |0    |
|B         |D         |0    |
|C         |A         |2    |
|C         |B         |0    |
|C         |D         |0    |
|D         |A         |0    |
|D         |B         |0    |
|D         |C         |0    |

但是,踢球者需要在一个需要将其作为单个查询运行的糟糕系统上执行。到目前为止,我有:

SELECT 
    X.[Category A]
    ,COUNT(*) AS [Count]
    ,X.[Category B]
FROM (
    SELECT 
        A.Category AS [Category A]
        ,B.Category AS [Category B]
    FROM (  
        SELECT 
            Category 
            ,Person
        FROM Categories
    ) AS A
    CROSS JOIN (
        SELECT
            Category 
            ,Person
        FROM Categories
    ) B WHERE A.Category = B.Category
) X GROUP BY X.[Category A], X.[Category B]

3 个答案:

答案 0 :(得分:0)

检查这个。

使用CTE

        with CTE as
        (
        select 
        Person,Category 
        from Categories    
        )
        select distinct c2.Category , c1.Category
        ,count(case when c1.person=c2.person then 1 end ) as Count
        from CTE C1, CTE c2    
        where c1.Category <> c2.Category
        group by c1.Category,c2.Category

没有CTE

        select distinct c2.Category , c1.Category
        ,count(case when c1.person=c2.person then 1 end ) as Count
        from Categories C1,  Categories c2    
        where c1.Category <> c2.Category
        group by c1.Category,c2.Category
  

输出:

enter image description here

答案 1 :(得分:0)

您可以使用CTE构建如下查询:

WITH CTE_CategoryCombinations AS 
( 
SELECT A.Category AS [Category A], B.Category AS [Category B]
FROM Categories AS A
INNER JOIN Categories AS B
ON A.Person = B.Person AND A.Category != B.Category )
SELECT [Category A], [Category B], COUNT(1)
FROM CTE_CategoryCombinations
GROUP BY [Category A], [Category B]
ORDER BY [Category A], [Category B];

这使用CTE,它是公用表表达式。我们创建CTE_CategoryCombinations的CTE将仅在其后的SELECT和GROUP BY cluase的持续时间内持续。它将不再可用,并且引用它将产生错误。

使用它的优点:

1)CTE提供了比使用Sub查询更快执行的好处,因为每次我们获取应用子查询的行时都会运行子查询。 CTE应该是解决这个问题的更快方法,这也应该得到理想的结果。

2)我们不使用交叉连接,交叉连接是一项昂贵的任务。另一方面,内部联接是获得我们期望的结果的更有效方式,因为它设置了我们比较类别的条件,因为我们只想比较相同人群的类别。

编辑2:

如果您不必坚持使用单个语句,则可以使用临时表。像这样:

INSERT INTO #Categories
FROM
(
SELECT A.Category AS [Category A], B.Category AS [Category B], A.Person
FROM Categories AS A
INNER JOIN Categories AS B
ON A.Person = B.Person AND A.Category != B.Category ) AS Temp;

SELECT [Category A], [Category B], COUNT(DISTINCT Person)
FROM #Categories
GROUP BY [Category A], [Category B]
ORDER BY [Category A], [Category B];

答案 2 :(得分:0)

尝试以下脚本,

DECLARE @TABLE  TABLE   (
    Category    VARCHAR(10)
    ,Person     VARCHAR(10)
)

INSERT INTO @TABLE
VALUES  ('A','P1'),('A','P2'),('A','P3')
       ,('B','P1'),('C','P2'),('C','P3')
       ,('D','P4')

SELECT  T1.Category     AS  CategoryA
        ,T2.Category    AS  CategoryB
        ,COUNT(CASE WHEN T1.Person=T2.Person THEN 1 END ) AS AB_Count
FROM    @TABLE  T1
INNER JOIN  @TABLE  T2  ON  T1.Category <>  T2.Category
GROUP BY T1.Category,T2.Category
ORDER BY 1