SQL 服务器 SELECT 第一次出现或如果没有出现 SELECT 其他条件

SQL Server SELECT first occurrence OR if no occurrence SELECT other criteria

我在尝试为此处的工作形成正确的 SQL 查询时遇到问题。我有两个 table,一个叫 CUSTOMER,另一个叫 CUSTOMER_CONTACT。为了简化这一点,我将只包括相关的列名。

CUSTOMER_ID 是 link 从 CUSTOMER_CONTACTCUSTOMER table 的外键。 CONTACT_VC 只是他们联系信息的条目号。每个客户可能有多个 CUSTOMER_CONTACT 记录,但他们将有一个唯一的 CONTACT_VCEMAIL 也可以是部分或全部 null/blank。

我需要 select 第一个 CUSTOMER_CONTACT 条目,其中 EMAILNOT NULL/空白但是如果 none 的 CUSTOMER_CONTACT 条目有一个电子邮件地址,然后 select CUSTOMER_CONTACT WHERE CONTACT_VC = 1

关于如何完成此操作有什么建议吗?

以下方法使用 ROW_NUMBER 根据您在每个 CUSTOMER_ID 组中的排序逻辑检索数字,然后按检索到的第一条记录进行过滤。

您可以尝试以下方法:

SELECT 
    * 
FROM (
    SELECT
        *,
        ROW_NUMBER() OVER (
            PARTITION BY CUSTOMER_ID
            ORDER BY (CASE WHEN EMAIL IS NOT NULL THEN 0 ELSE 1 END),CONTACT_VC 
        ) as rn
    FROM
        CUSTOMER_CONTACT
) t
WHERE rn=1

如果您想将此连接到客户table,您可以将上述查询用作子查询,例如

SELECT
   c.*,
   contact.*
FROM
   CUSTOMER c 
INNER JOIN (
    SELECT
        *,
        ROW_NUMBER() OVER (
            PARTITION BY CUSTOMER_ID
            ORDER BY (CASE WHEN EMAIL IS NOT NULL THEN 0 ELSE 1 END),CONTACT_VC 
        ) as rn
    FROM
        CUSTOMER_CONTACT
) contact ON c.ID = contact.CUSTOMER_ID and contact.rn=1

这是与 ggordon 几乎相同的答案,但我使用了一个常见的 table 表达式,我认为子查询部分中的顺序应该先按 CONTACT_VS 然后按非 NULL 电子邮件地址.我为 运行 创建了一些非常简单的测试数据:

DECLARE @CUSTOMER AS TABLE
(
    [ID]           INT         NOT NULL,
    [CUSTOMERNAME] VARCHAR(10) NOT NULL
);

INSERT INTO @CUSTOMER
(
    [ID],
    [CUSTOMERNAME]
)
VALUES
(1, 'Alice'),
(2, 'Bob'),
(3, 'Cathy');

DECLARE @CUSTOMER_CONTACT AS TABLE
(
    [ID]          INT         NOT NULL,
    [CUSTOMER_ID] INT         NOT NULL,
    [CONTACT_VC]  INT         NOT NULL,
    [EMAIL]       VARCHAR(40) NULL
);

INSERT INTO @CUSTOMER_CONTACT
(
    [ID],
    [CUSTOMER_ID],
    [CONTACT_VC],
    [EMAIL]
)
VALUES
(1, 1, 1, 'alice@email.com'),
(2, 1, 2, 'alice@gmail.com'),
(3, 2, 1, NULL),
(4, 2, 2, 'bob@work.com'),
(5, 3, 1, NULL),
(6, 3, 2, NULL),
(7, 3, 3, NULL);

;WITH [cc]
AS (SELECT [ID],
           [CUSTOMER_ID],
           [CONTACT_VC],
           [EMAIL],
           ROW_NUMBER() OVER (PARTITION BY [CUSTOMER_ID]
                              ORDER BY [CONTACT_VC],
                                       (CASE WHEN [EMAIL] IS NOT NULL THEN
                                                 0
                                             ELSE
                                                 1
                                        END
                                       )
                             ) AS [rn]
    FROM   @CUSTOMER_CONTACT)
SELECT [c].[ID], [c].[CUSTOMERNAME], [cc].[ID], [cc].[CUSTOMER_ID], [cc].[CONTACT_VC], [cc].[EMAIL]
FROM   @CUSTOMER AS [c]
       INNER JOIN [cc]
           ON [c].[ID] = [cc].[CUSTOMER_ID]
              AND [cc].[rn] = 1;

select * from CUSTOMER_CONTACT where EMAIL IS NOT NULL 
union all 
select * from CUSTOMER_CONTACT where 
    (CONTACT_VC=1 and NOT EXISTS (select 1 FROM CUSTOMER_CONTACT where EMAIL IS NOT NUL)
order by CONTACT_VC asc limit 1