SQL 服务器 - 减少查询中列包含 NULL 的近乎重复的记录?
SQL Server - Mitigating near-duplicate records where columns contain NULL in a query?
上下文
我有一个 SQL 查询连接到直接显示结果的 Windows Forms DataGridView 的数据源。到目前为止,我已经设法让它获取所有联系人及其相关数据,但是有一个问题...
问题
由于 phone 及其类型在数据库中的保存方式,联系人显示时会显示与联系人关联的每个 phone 的新记录,我只需要它来显示每个 phone 类型的 'TOP 1'(如果存在)。
我尝试了几种我能想到并在互联网上找到的潜在解决方案,我尝试使用DISTINCT
但它似乎对记录集没有任何影响,我也尝试了GROUP BY
但我最终遇到了问题,因为它需要聚合函数。
USE [Customer]
SELECT
co.[Contact ID] AS [ID],
co.[First Name] AS [First Name],
co.[Last Name] AS [Last Name],
cu.[Name] AS [Customer Name],
(SELECT TOP 1 te.[Number] WHERE tt.[Telephone Type] = 'Work') AS [Work Phone],
(SELECT TOP 1 te.[Number] WHERE tt.[Telephone Type] = 'Mobile') AS [Mobile Phone],
em.[Address] AS [Email Address]
FROM
(
(
(
(
(
(
([Contact] AS co
INNER JOIN
[Customer Contact] AS cc ON cc.[Contact ID] = co.[Contact ID])
INNER JOIN
[Customer] AS cu ON cu.[Customer ID] = cc.[Customer ID])
INNER JOIN
[Contact Email] AS ce ON ce.[Contact ID] = cc.[Contact ID])
INNER JOIN
[Email] AS em ON em.[Email ID] = ce.[Email ID])
INNER JOIN
[Contact Telephone] AS ct ON ct.[Contact ID] = cc.[Contact ID])
INNER JOIN
[Telephone] AS te ON te.[Telephone ID] = ct.[Telephone ID])
INNER JOIN
[Telephone Type] AS tt ON tt.[Telephone Type ID] = ct.[Telephone Type ID])
--Only want to specify 'Work' and 'Mobile' out of the three phone types
WHERE
tt.[Telephone Type] <> 'Home'
--Specifying a single contact for the example
AND co.[Last Name] = 'Wayne'
ORDER BY
cu.[Name] ASC;
这是当前查询的记录集returns。
如您所见,两条记录有 NULL
个值不同。
ID
First Name
Last Name
Customer
Work Phone
Mobile Phone
Email Address
1
e002a448...
Bruce
Wayne
Wayne Tech
(worknumber)
NULL
bruce.wayne@waynetech.com
2
e002a448...
Bruce
Wayne
Wayne Tech
NULL
(mobilenumber)
bruce.wayne@waynetech.com
这是我正在尝试获取的记录集 - 如您所见,与联系人关联的第一个作品 phone 和手机 phone 包含在一个记录中,并且没有更多记录出现.
ID
First Name
Last Name
Customer
Work Phone
Mobile Phone
Email Address
1
e002a448...
Bruce
Wayne
Wayne Tech
(worknumber)
(mobilenumber)
bruce.wayne@waynetech.com
TLDR: 我不知道如何为数据库中的每个联系人显示单个记录,而不是为每个不同的关联 phone 每个联系人的编号。
您在查询中的某个时刻需要聚合或其他东西。我的建议是使用 OUTER APPLY
:
SELECT co.[Contact ID] AS [ID],
co.[First Name] AS [First Name],
co.[Last Name] AS [Last Name],
cu.[Name] AS [Customer Name],
p.*
em.[Address] AS [Email Address]
FROM [Contact] co JOIN
[Customer Contact] cc
ON cc.[Contact ID] = co.[Contact ID] JOIN
[Customer] cu
ON cu.[Customer ID] = cc.[Customer ID] JOIN
[Contact Email] ce
ON ce.[Contact ID] = cc.[Contact ID] JOIN
[Email] em
ON em.[Email ID] = ce.[Email ID] OUTER APPLY
(SELECT MAX(CASE WHEN tt.[Telephone Type] = 'Work' THEN te.Number END) as work,
MAX(CASE WHEN tt.[Telephone Type] = 'Mobile' THEN te.Number END) as mobile
FROM [Contact Telephone] ct JOIN
[Telephone] te
ON te.[Telephone ID] = ct.[Telephone ID] JOIN
[Telephone Type] tt
ON tt.[Telephone Type ID] = ct.[Telephone Type ID]
WHERE ct.[Contact ID] = cc.[Contact ID]
) p
--Only want to specify 'Work' and 'Mobile' out of the three phone types
WHERE co.[Last Name] = 'Wayne'
ORDER BY cu.[Name] ASC;
上下文
我有一个 SQL 查询连接到直接显示结果的 Windows Forms DataGridView 的数据源。到目前为止,我已经设法让它获取所有联系人及其相关数据,但是有一个问题...
问题
由于 phone 及其类型在数据库中的保存方式,联系人显示时会显示与联系人关联的每个 phone 的新记录,我只需要它来显示每个 phone 类型的 'TOP 1'(如果存在)。
我尝试了几种我能想到并在互联网上找到的潜在解决方案,我尝试使用DISTINCT
但它似乎对记录集没有任何影响,我也尝试了GROUP BY
但我最终遇到了问题,因为它需要聚合函数。
USE [Customer]
SELECT
co.[Contact ID] AS [ID],
co.[First Name] AS [First Name],
co.[Last Name] AS [Last Name],
cu.[Name] AS [Customer Name],
(SELECT TOP 1 te.[Number] WHERE tt.[Telephone Type] = 'Work') AS [Work Phone],
(SELECT TOP 1 te.[Number] WHERE tt.[Telephone Type] = 'Mobile') AS [Mobile Phone],
em.[Address] AS [Email Address]
FROM
(
(
(
(
(
(
([Contact] AS co
INNER JOIN
[Customer Contact] AS cc ON cc.[Contact ID] = co.[Contact ID])
INNER JOIN
[Customer] AS cu ON cu.[Customer ID] = cc.[Customer ID])
INNER JOIN
[Contact Email] AS ce ON ce.[Contact ID] = cc.[Contact ID])
INNER JOIN
[Email] AS em ON em.[Email ID] = ce.[Email ID])
INNER JOIN
[Contact Telephone] AS ct ON ct.[Contact ID] = cc.[Contact ID])
INNER JOIN
[Telephone] AS te ON te.[Telephone ID] = ct.[Telephone ID])
INNER JOIN
[Telephone Type] AS tt ON tt.[Telephone Type ID] = ct.[Telephone Type ID])
--Only want to specify 'Work' and 'Mobile' out of the three phone types
WHERE
tt.[Telephone Type] <> 'Home'
--Specifying a single contact for the example
AND co.[Last Name] = 'Wayne'
ORDER BY
cu.[Name] ASC;
这是当前查询的记录集returns。
如您所见,两条记录有 NULL
个值不同。
ID | First Name | Last Name | Customer | Work Phone | Mobile Phone | Email Address | |
---|---|---|---|---|---|---|---|
1 | e002a448... | Bruce | Wayne | Wayne Tech | (worknumber) | NULL | bruce.wayne@waynetech.com |
2 | e002a448... | Bruce | Wayne | Wayne Tech | NULL | (mobilenumber) | bruce.wayne@waynetech.com |
这是我正在尝试获取的记录集 - 如您所见,与联系人关联的第一个作品 phone 和手机 phone 包含在一个记录中,并且没有更多记录出现.
ID | First Name | Last Name | Customer | Work Phone | Mobile Phone | Email Address | |
---|---|---|---|---|---|---|---|
1 | e002a448... | Bruce | Wayne | Wayne Tech | (worknumber) | (mobilenumber) | bruce.wayne@waynetech.com |
TLDR: 我不知道如何为数据库中的每个联系人显示单个记录,而不是为每个不同的关联 phone 每个联系人的编号。
您在查询中的某个时刻需要聚合或其他东西。我的建议是使用 OUTER APPLY
:
SELECT co.[Contact ID] AS [ID],
co.[First Name] AS [First Name],
co.[Last Name] AS [Last Name],
cu.[Name] AS [Customer Name],
p.*
em.[Address] AS [Email Address]
FROM [Contact] co JOIN
[Customer Contact] cc
ON cc.[Contact ID] = co.[Contact ID] JOIN
[Customer] cu
ON cu.[Customer ID] = cc.[Customer ID] JOIN
[Contact Email] ce
ON ce.[Contact ID] = cc.[Contact ID] JOIN
[Email] em
ON em.[Email ID] = ce.[Email ID] OUTER APPLY
(SELECT MAX(CASE WHEN tt.[Telephone Type] = 'Work' THEN te.Number END) as work,
MAX(CASE WHEN tt.[Telephone Type] = 'Mobile' THEN te.Number END) as mobile
FROM [Contact Telephone] ct JOIN
[Telephone] te
ON te.[Telephone ID] = ct.[Telephone ID] JOIN
[Telephone Type] tt
ON tt.[Telephone Type ID] = ct.[Telephone Type ID]
WHERE ct.[Contact ID] = cc.[Contact ID]
) p
--Only want to specify 'Work' and 'Mobile' out of the three phone types
WHERE co.[Last Name] = 'Wayne'
ORDER BY cu.[Name] ASC;