メモ:SQL Server 2017 Graph の NOT MATCH

ぼちぼち SQL Server 2017 の Graph 触ってます。
Graph processing with SQL Server and Azure SQL Database | Microsoft Docs

MATCH は、NOT 書けないようなので、代わりに NOT EXISTS を使うようです。
MATCH (SQL Graph) | Microsoft Docs

例:片思いの人を取得する。
f:id:odashinsuke:20171031231232p:plain
A さんと D さんが片思いなデータを作ってみます。

create table [人] ( [名前] nvarchar(20) ) as node
create table [好き] as edge

insert into [人] values (N'Aさん'), (N'Bさん'), (N'Cさん'), (N'Dさん'), (N'Eさん')
declare @id1 nvarchar(1000) = (select $node_id from [人] where [名前] = N'Aさん')
declare @id2 nvarchar(1000) = (select $node_id from [人] where [名前] = N'Bさん')
declare @id3 nvarchar(1000) = (select $node_id from [人] where [名前] = N'Cさん')
declare @id4 nvarchar(1000) = (select $node_id from [人] where [名前] = N'Dさん')
declare @id5 nvarchar(1000) = (select $node_id from [人] where [名前] = N'Eさん')

insert into [好き] values
(@id1, @id2)
, (@id2, @id3)
, (@id3, @id2)
, (@id4, @id5)

まず繋がってる人を取ってみます。

select [誰さん].[名前] as [誰々さんが], [好きな人].[名前] as [好きな人]
from [人] [誰さん], [好き], [人] [好きな人]
where match ([誰さん] - ([好き]) -> [好きな人])
誰々さんが 好きな人
Aさん Bさん
Bさん Cさん
Cさん Bさん
Dさん Eさん

ここから、両想いの Bさん、Cさんを除くと求めたい片思いの人が取れます。
not match (誰さん <- ([好き]) - [好きな人]) を追加したら良いのかなと試したところエラーが出ました。

select [誰さん].[名前] as [誰々さんが], [好きな人].[名前] as [好きな人]
from [人] [誰さん], [好き], [人] [好きな人]
where match ([誰さん] - ([好き]) -> [好きな人])
and not match ([誰さん] <- ([好き]) - [好きな人])
メッセージ 13903、レベル 16、状態 1、行 23
エッジ テーブル '好き' が複数の MATCH パターンで使用されています。
メッセージ 13905、レベル 16、状態 1、行 23
MATCH 句は、OR や NOT を使用して他の式と直接組み合わせることができません。

MATCH は、OR や NOT と一緒に使えないようです。
Graph extensions in Microsoft SQL Server 2017 and Azure SQL Database
にも記載がありました。
スライドの P32-34 辺りです。

というわけで書き直します。

select [誰さん].[名前] as [誰々さんが], [好きな人].[名前] as [好きな人]
from [人] [誰さん], [好き], [人] [好きな人]
where match ([誰さん] - ([好き]) -> [好きな人])
and not exists (
  select * from [好き] [nest] 
  where match ([誰さん] <- ([nest]) - [好きな人])
)
誰々さんが 好きな人
Aさん Bさん
Dさん Eさん

これで取れました!

もう1個のエラーの エッジは1個のマッチでしか使えないのも少し試します。
両想いを取るこれでもエラーが出ました。

select [誰さん].[名前] as [誰々さんが], [好きな人].[名前] as [好きな人]
from [人] [誰さん], [好き], [人] [好きな人]
where match ([誰さん] - ([好き]) -> [好きな人] 
and [誰さん] <- ([好き]) - [好きな人])

正しくはこうなります。

select [誰さん].[名前] as [誰々さんが], [好きな人].[名前] as [好きな人]
from [人] [誰さん], [好き] [好1], [人] [好きな人], [好き] [好2]
where match ([誰さん] - ([好1]) -> [好きな人] 
and [誰さん] <- ([好2]) - [好きな人])