T-SQL按唯一多对多关系性能分组

T-SQL按唯一多对多关系性能分组,sql,sql-server,database,query-performance,Sql,Sql Server,Database,Query Performance,我正在尝试创建一个SQL查询,它可以按唯一的多对多关系进行分组。我有一个事件表,可以有一个或多个艺术家。我想将这些活动分组,但前提是它们没有相同的阵容(完全相同的艺术家表演)。如果他们有完全相同的阵容,我只想得到最新(=活动日期)的活动 经过一些调查,它似乎将不得不做使用外部应用程序,但我真的不明白它 更新 我需要在结果集中为每个艺术家、每个事件指定单独的行,如预期结果表中所述。它们(或艺术家id)不应连接在单个字段中 更新2 我确实得到了下面的查询来执行所需的操作,但是EXISTS条件的性能很

我正在尝试创建一个SQL查询,它可以按唯一的多对多关系进行分组。我有一个事件表,可以有一个或多个艺术家。我想将这些活动分组,但前提是它们没有相同的阵容(完全相同的艺术家表演)。如果他们有完全相同的阵容,我只想得到最新(=活动日期)的活动

经过一些调查,它似乎将不得不做使用外部应用程序,但我真的不明白它

更新

我需要在结果集中为每个艺术家、每个事件指定单独的行,如预期结果表中所述。它们(或艺术家id)不应连接在单个字段中

更新2

我确实得到了下面的查询来执行所需的操作,但是EXISTS条件的性能很差。能否以更有效的方式重新编写

注: 使用EXISTS条件的SQL语句效率非常低,因为对子查询对外部查询表中的每一行都重新运行。有更有效的方法来编写大多数不使用EXISTS条件的查询

模式

事件表

 x-----------x---------x------------x
 |  EventId  |   Name  | Date       |
 x-----------x---------x------------x
 |   1       |   E1    | 2016-01-01 |
 |   2       |   E2    | 2016-01-02 |
 |   3       |   E3    | 2016-01-03 |
 |   4       |   E4    | 2016-01-04 |
 |   5       |   E5    | 2016-01-05 |
 |   6       |   E6    | 2016-01-06 |
 |   7       |   E7    | 2016-01-07 |
 |   8       |   E8    | 2016-01-08 |
 x-----------x---------x------------x
 x-----------x-------------x
 |  EventId  |   ArtistId  |
 x-----------x-------------x
 |   1       |   1         |
 |   1       |   2         |
 |   2       |   3         |
 |   3       |   2         |
 |   3       |   1         |
 |   4       |   5         |
 |   4       |   6         |
 |   5       |   4         |
 |   6       |   5         |
 |   8       |   3         |
 x-----------x-------------x
 x------------x---------x--------------x
 |  ArtistId  |   Name  |   Bio        |
 x------------x---------x--------------x
 |   1        |   A1    | BIO1         |
 |   2        |   A2    | BIO2         |
 |   3        |   A3    | BIO3         |
 |   4        |   A4    | BIO4         |
 |   5        |   A5    | BIO5         |
 |   6        |   A6    | BIO6         |
 x------------x---------x--------------x
头条新闻表

 x-----------x---------x------------x
 |  EventId  |   Name  | Date       |
 x-----------x---------x------------x
 |   1       |   E1    | 2016-01-01 |
 |   2       |   E2    | 2016-01-02 |
 |   3       |   E3    | 2016-01-03 |
 |   4       |   E4    | 2016-01-04 |
 |   5       |   E5    | 2016-01-05 |
 |   6       |   E6    | 2016-01-06 |
 |   7       |   E7    | 2016-01-07 |
 |   8       |   E8    | 2016-01-08 |
 x-----------x---------x------------x
 x-----------x-------------x
 |  EventId  |   ArtistId  |
 x-----------x-------------x
 |   1       |   1         |
 |   1       |   2         |
 |   2       |   3         |
 |   3       |   2         |
 |   3       |   1         |
 |   4       |   5         |
 |   4       |   6         |
 |   5       |   4         |
 |   6       |   5         |
 |   8       |   3         |
 x-----------x-------------x
 x------------x---------x--------------x
 |  ArtistId  |   Name  |   Bio        |
 x------------x---------x--------------x
 |   1        |   A1    | BIO1         |
 |   2        |   A2    | BIO2         |
 |   3        |   A3    | BIO3         |
 |   4        |   A4    | BIO4         |
 |   5        |   A5    | BIO5         |
 |   6        |   A6    | BIO6         |
 x------------x---------x--------------x
艺术家表

 x-----------x---------x------------x
 |  EventId  |   Name  | Date       |
 x-----------x---------x------------x
 |   1       |   E1    | 2016-01-01 |
 |   2       |   E2    | 2016-01-02 |
 |   3       |   E3    | 2016-01-03 |
 |   4       |   E4    | 2016-01-04 |
 |   5       |   E5    | 2016-01-05 |
 |   6       |   E6    | 2016-01-06 |
 |   7       |   E7    | 2016-01-07 |
 |   8       |   E8    | 2016-01-08 |
 x-----------x---------x------------x
 x-----------x-------------x
 |  EventId  |   ArtistId  |
 x-----------x-------------x
 |   1       |   1         |
 |   1       |   2         |
 |   2       |   3         |
 |   3       |   2         |
 |   3       |   1         |
 |   4       |   5         |
 |   4       |   6         |
 |   5       |   4         |
 |   6       |   5         |
 |   8       |   3         |
 x-----------x-------------x
 x------------x---------x--------------x
 |  ArtistId  |   Name  |   Bio        |
 x------------x---------x--------------x
 |   1        |   A1    | BIO1         |
 |   2        |   A2    | BIO2         |
 |   3        |   A3    | BIO3         |
 |   4        |   A4    | BIO4         |
 |   5        |   A5    | BIO5         |
 |   6        |   A6    | BIO6         |
 x------------x---------x--------------x

此解决方案假定您可以将给定事件的所有ArtistId连接到一个逗号分隔的列表中(没有空格),该列表将适合
varchar(1000
),如果您的所有ArtistId值都在数十亿(10位)中,则为90
Varchar(8000)
也可以工作,但是如果必须使用
Varchar(max)
,事情可能会变得不确定

我用它来设置数据:

CREATE TABLE Event
 (
   EventId  int  not null
  ,Name     varchar(50)  not null
  ,Date     date  not null
 )

INSERT Event values
  (1,'E1', 'Jan 1, 2016')
 ,(2,'E2', 'Jan 2, 2016')
 ,(3,'E3', 'Jan 3, 2016')
 ,(4,'E4', 'Jan 4, 2016')
 ,(5,'E5', 'Jan 5, 2016')
 ,(6,'E6', 'Jan 6, 2016')
 ,(7,'E7', 'Jan 7, 2016')
 ,(8,'E8', 'Jan 8, 2016')

CREATE TABLE Headliner
 (
   EventId  int  not null
  ,ArtistId int  not null
 )

INSERT Headliner values
  (1,1)
 ,(1,2)
 ,(2,3)
 ,(3,2)
 ,(3,1)
 ,(4,5)
 ,(4,6)
 ,(5,4)
 ,(6,5)
 ,(8,3)

CREATE TABLE Artist
 (
   ArtistId  int  not null
  ,Name      varchar(50)  not null
  ,Bio       varchar(50)  not null
 )

INSERT Artist values
   (1, 'A1', 'BI01')
  ,(2, 'A2', 'BI02')
  ,(3, 'A3', 'BI03')
  ,(4, 'A4', 'BI04')
  ,(5, 'A5', 'BI05')
  ,(6, 'A6', 'BI06')

SELECT
   EvntId
  ,isnull(
 from Headliner
 group by EventId
接下来,我创建了一个函数来连接给定EventId的所有ArtistID:

IF objectproperty(object_id('dbo.Concat'), 'isScalarFunction') = 1
    DROP FUNCTION dbo.Concat

GO
CREATE FUNCTION dbo.Concat
 (
  @EventId  int
 )
RETURNS varchar(1000)
BEGIN
    DECLARE @Concatenated  varchar(1000)

    SELECT @Concatenated = isnull(@Concatenated + ',' , '') + cast(ArtistId as varchar(10))
     from Headliner
     where EventId = @EventId
     order by ArtistId

    RETURN @Concatenated
END
GO
这允许我们使用双重嵌套的CTE来完成工作。(如果性能有问题,可以使用临时表,但这似乎不太可能。)


额外的奖金,它甚至可以解释“没有艺术家”的情况。性能和其他无法估量的因素取决于正在使用的表格和集合的大小。

。。。404错误页面?我认为您的示例和结果数据与EventId 7和8@PhilipKelley我看不出前后矛盾。事件7没有标题行,而8有一个标题行(艺术家id=3),但这是事件id 2的副本。@Jodrell链接应该是:但我不想在单个单元格中串联,而是返回多行-请参见预期结果。啊,我错过了空值。将“无艺术家”作为有效的结果集会使问题变得更加棘手。@Nielsen我不希望结果集中的值串联在一起(请参见预期结果)。我需要把它们分开排。尽管如此,还是要感谢您的努力。实际上,这会在单独的行中返回值。试试看!