如何对依赖于其他列的名称进行分组

时间:2015-03-18 14:20:17

标签: sql-server sql-server-2008

我有一张如下表格。

enter image description here

CREATE TABLE #Test
(
  CustId INT ,
  CustName VARCHAR(100) ,
  CustHeading VARCHAR(100)
)
INSERT INTO #Test

SELECT '1','john carroll','Heading 1'
UNION ALL
SELECT '1','john carroll','Heading 2' 
UNION ALL
SELECT '2','john c','Heading 1' 
UNION ALL
SELECT '2','john c','Heading 2' 
UNION ALL
SELECT '2','john c','Heading 3' 
UNION ALL
SELECT '3','john lynch','Heading 1' 
UNION ALL
SELECT '4','john carroll lynch','Heading 1' 
UNION ALL
SELECT '4','john carroll lynch','Heading 4' 
UNION ALL
SELECT '4','john carroll lynch','Heading 5' 
UNION ALL
SELECT '5','john c lynch','Heading 1' 
UNION ALL
SELECT '5','john c lynch','Heading 3' 
UNION ALL
SELECT '6','john c l','Heading 11' 
UNION ALL
SELECT '6','john c l','Heading 12' 
UNION ALL
SELECT '7','john c ln','Heading 1' 
UNION ALL
SELECT '7','john c ln','Heading 2' 
UNION ALL
SELECT '2','john c','Heading 11' 
UNION ALL
SELECT '2','john c','Heading 12'

在此,我们需要对其中包含至少两个匹配标题的客户进行分组。

例如,custID :: 1,2和7有两个匹配CustHeading :: 标题1和标题2 ,因此它们被分组.CustID :: 2和两个匹配CustHeading :: 标题1和标题3 ,它们也可以分组。请让我知道如何实现这个

不使用WHILE循环

enter image description here

提前致谢。

2 个答案:

答案 0 :(得分:1)

SELECT 
DISTINCT
    CASE WHEN c.num = 1 THEN a.CustId
         ELSE a.[_CustId]
    END ,
    CASE WHEN c.num = 1 THEN a.CustName
         ELSE a.[_CustName]
    END ,
    'M' + CAST(DENSE_RANK() OVER ( ORDER BY mx, mn ) AS VARCHAR(100)) AS gr_nbr
FROM
    (
      SELECT
        a.CustId ,
        a.CustName ,
        c.CustId _CustId ,
        c.CustName _CustName,
        MAX(a.CustHeading) mx,
        MIN(a.CustHeading) mn
      FROM
        #Test a
        JOIN #Test c ON c.CustHeading = a.CustHeading
                     AND c.CustId > a.CustId
      GROUP BY
        a.CustId ,
        a.CustName ,
        c.CustId ,
        c.CustName
      HAVING
        MAX(a.CustHeading) <> MIN(a.CustHeading)
    ) a
    JOIN #Test b ON b.CustId = a.[_CustId]
    CROSS JOIN (
                 SELECT
                    1 num
                 UNION ALL
                 SELECT
                    2 num
               ) AS c
ORDER BY
    3 ,
    1

答案 1 :(得分:1)

抱歉,我的大脑今天不起作用了。我确信有一种更简单的方法可以做到这一点,但我现在可以思考。这对我来说似乎很好。如果需要任何更改,请告诉我。

CREATE TABLE #Test
(
  CustId INT ,
  CustName VARCHAR(100) ,
  CustHeading VARCHAR(100)
)
INSERT INTO #Test

SELECT '1','john carroll','Heading 1'
UNION ALL
SELECT '1','john carroll','Heading 2' 
UNION ALL
SELECT '2','john c','Heading 1' 
UNION ALL
SELECT '2','john c','Heading 2' 
UNION ALL
SELECT '2','john c','Heading 3' 
UNION ALL
SELECT '3','john lynch','Heading 1' 
UNION ALL
SELECT '4','john carroll lynch','Heading 1' 
UNION ALL
SELECT '4','john carroll lynch','Heading 4' 
UNION ALL
SELECT '4','john carroll lynch','Heading 5' 
UNION ALL
SELECT '5','john c lynch','Heading 1' 
UNION ALL
SELECT '5','john c lynch','Heading 3' 
UNION ALL
SELECT '6','john c l','Heading 11' 
UNION ALL
SELECT '6','john c l','Heading 12' 
UNION ALL
SELECT '7','john c ln','Heading 1' 
UNION ALL
SELECT '7','john c ln','Heading 2' 
UNION ALL
SELECT '2','john c','Heading 11' 
UNION ALL
SELECT '2','john c','Heading 12';


WITH CTE_Heading
AS
(
    SELECT DISTINCT custHeading
    FROM #Test
),
CTE_Paired_Headings
AS
(
    SELECT  A.custHeading AS Head1,
            B.CustHeading AS Head2
    FROM CTE_Heading A
    INNER JOIN CTE_Heading B
    ON A.custHeading < B.custHeading
),
CTE_Matching_Cust
AS
(
SELECT  A.Head1,
        A.Head2,
        B.CustId,
        B.CustName
FROM CTE_Paired_Headings A
INNER JOIN #Test B
    ON A.Head1 = B.CustHeading
    OR A.Head2 = B.CustHeading
GROUP BY A.Head1,A.Head2,B.CustId,B.CustName
HAVING COUNT(*) >= 2
),
CTE_HeadingGroups
AS
(
SELECT  'M' + CAST(ROW_NUMBER() OVER (ORDER BY Head1,Head2) AS VARCHAR(5)) MatchingID,
        Head1,
        Head2
FROM CTE_Matching_Cust
GROUP BY Head1,Head2
HAVING COUNT(*) >= 2
)

SELECT  B.CustId,
        B.CustName,
        A.MatchingID
FROM CTE_HeadingGroups A
INNER JOIN CTE_Matching_Cust B
ON  A.Head1 = B.Head1
    AND A.Head2 = B.Head2
ORDER BY 3,1


DROP TABLE #Test

结果:

CustId      CustName                 MatchingID
-----------------------------------------------
1           john carroll             M1
2           john c                   M1
7           john c ln                M1
2           john c                   M2
5           john c lynch             M2
2           john c                   M3
6           john c l                 M3