过滤交叉连接的结果以选择不同的列组合

时间:2018-01-15 04:27:13

标签: sql sql-server tsql

我有Cross加入3个表,现在我想使用组合列值过滤结果。我的意思是,如果一行有3列的值(a,b,c),那么它被视为与具有这3个值(b,c,a)的行或a,b和的任何其他组合相同C。

生成结果的查询是:

;WITH CTE
     AS (SELECT T1.LastName                                       AS T1LASTNAME,
                T2.LastName                                       AS T2LASTNAME,
                T3.LastName                                       AS T3LASTNAME,
                ( T1.TOTALSALES + T2.TOTALSALES + T3.TOTALSALES ) AS TOTALSALES,
                ( T1.SALARY + T2.SALARY + T3.SALARY )             AS TOTALSALARY
         FROM   #TOPSALESPERSON AS T1
                CROSS JOIN #TOPSALESPERSON AS T2
                CROSS JOIN #TOPSALESPERSON AS T3
         WHERE  T1.BusinessEntityID != T2.BusinessEntityID
                AND T2.BusinessEntityID != T3.BusinessEntityID
                AND T1.BusinessEntityID != T3.BusinessEntityID
                AND T1.NAME != T2.NAME
                AND T1.NAME != T3.NAME
                AND T3.NAME != T2.NAME)
SELECT DISTINCT *
FROM   CTE
WHERE  CTE.TOTALSALARY < 210000
ORDER  BY TOTALSALES DESC 

所以在这里,这3行应该被过滤到一行:

T1LASTNAME  T2LASTNAME  T3LASTNAME   TOTALSALES  TOTALSALARY
------------------------------------------------------------
Campbell    Mitchell    Saraiva      2924710.74  195000.00
Campbell    Saraiva     Mitchell     2924710.74  195000.00
Mitchell    Campbell    Saraiva      2924710.74  195000.00

以下是架构和数据的SQL小提琴链接: http://sqlfiddle.com/#!9/c456d8/1/0

由于

2 个答案:

答案 0 :(得分:4)

将名称限制更改为以下逻辑:

T1.NAME <= T2.NAME AND
T1.NAME <= T3.NAME AND
T2.NAME <= T3.NAME

这解决了您的原始问题,因为现在这三个名称只能按升序显示。

;WITH CTE
 AS (SELECT T1.LastName                                       AS T1LASTNAME,
            T2.LastName                                       AS T2LASTNAME,
            T3.LastName                                       AS T3LASTNAME,
            ( T1.TOTALSALES + T2.TOTALSALES + T3.TOTALSALES ) AS TOTALSALES,
            ( T1.SALARY + T2.SALARY + T3.SALARY )             AS TOTALSALARY
     FROM   #TOPSALESPERSON AS T1
            CROSS JOIN #TOPSALESPERSON AS T2
            CROSS JOIN #TOPSALESPERSON AS T3
     WHERE  T1.BusinessEntityID != T2.BusinessEntityID
            AND T2.BusinessEntityID != T3.BusinessEntityID
            AND T1.BusinessEntityID != T3.BusinessEntityID
            AND T1.NAME <= T2.NAME
            AND T1.NAME <= T3.NAME
            AND T2.NAME <= T3.NAME)

请注意,如果两个或三个名称相同,我们仍然可以获得重复记录。但是你的SELECT DISTINCT实际上会处理这个问题并删除那些重复的内容。

答案 1 :(得分:0)

据我所知,这不是一种不用编写自定义函数就可以做到这一点的方法。您可以编写一个以两个字符串作为输入的函数。第一个输入字符串是您在示例中提到的名称列的串联。连接应该通过您选择的分隔符来划分字符串。第二个输入字符串应该是您的分隔符。

以下是我如何连接名称:

concat(t1lastname, '--', t2lastname, '--', t3lastname)

然后,您的自定义函数接受输入字符串并通过分隔符对字符串进行标记并对其进行排序。一旦对名称进行了排序,它们就会重新连接在一起,并按排序顺序返回。

function sort_delimited_string(concatenated_string, delimiter_string) 
{
    ...
    return concatenated_sorted_string;
}

你的查询看起来像这样:

select distinct(sort_delmited_string(concat(t1lastname, '--', t2lastname, '--', t3lastname), '--')) from table1;