从基于优先级的值列表

时间:2018-04-13 11:44:38

标签: sql sql-server tsql

如果标题令人困惑,我很难道歉,我发现很难准确地说出我正在寻找的内容。如果有人可以指出我正确的方向,或者如果存在其他问题,我将非常感谢您。

如果我在表格中有以下值,我希望编写一个查询,为每个[ContactID]选择一条记录。

如果记录存在[PhoneType]'Mob',然后 - > '工作',然后 - > 'Hom,查询应首先检查'并返回匹配的第一条记录,并忽略[ContactID]

的其他记录
CREATE TABLE #Test
(
    [ContactID] int,
    [PhoneNo] NVARCHAR(20),
    [PhoneType] NVARCHAR(20)
);

INSERT INTO #Test
(
    [ContactID],
    [PhoneNo],
    [PhoneType]
)
VALUES
    (1, '51351301', 'Mob'),
    (1, '999', 'Work'),
    (1, '8461', 'Hom'),
    (2, '213231321', 'Work'),
    (3, '848136', 'Mob'),
    (4, '23231', 'Hom'),
    (4, '2132315', 'Work')

结果看起来像

(1, '51351301', 'Mob'),
(2, '213231321', 'Work'),
(3, '848136', 'Mob'),
(4, '2132315', 'Work')

3 个答案:

答案 0 :(得分:3)

window function top(1)结合使用

试试这个:

SELECT * 
FROM(
    SELECT TOP(1) WITH ties *
    FROM #Test t
    ORDER BY ROW_NUMBER() OVER (PARTITION BY contactid
                                ORDER BY (CASE WHEN phoneType = 'Mob' THEN 1
                                            WHEN phoneType = 'Work' THEN 2
                                            WHEN phoneType = 'Hom' THEN 3
                                            ELSE 4
                                            END)
                                   )
    )D
ORDER BY D.ContactID

答案 1 :(得分:2)

您可以使用row_number()

select t.*
from (select t.*,
             row_number() over (partition by contactid
                                order by (case when phoneType = 'Mob' then 1
                                               when phoneType = 'Work' then 2
                                               when phoneType = 'Hom' then 3
                                               else 4
                                          end)
                               ) as seqnum
      from #test t
     ) t
where seqnum = 1;

如果您有一个包含联系人的单独表格,您还可以使用apply

select t.*
from contacts c cross apply
     (select top (1) t.*
      from #test t
      where c.contactid = t.contactid
      order by charindex(phonetype, 'Mob,Work,Hom')
     ) t;

请注意,这会使用简写进行排序。这适用于您的手机类型 - 但假设这些只是三种。

答案 2 :(得分:2)

我认为这会做你想要的。它为每个ContactID设置一个行ID,并且只为每个ContactID拉出第一个

CREATE TABLE #Test
(
    [ContactID] int,
    [PhoneNo] NVARCHAR(20),
    [PhoneType] NVARCHAR(20)
);

--DROP TABLE #Test

INSERT INTO #Test
(
    [ContactID],
    [PhoneNo],
    [PhoneType]
)
VALUES
    (1, '51351301', 'Mob'),
    (1, '999', 'Work'),
    (1, '8461', 'Hom'),
    (2, '213231321', 'Work'),
    (3, '848136', 'Mob'),
    (4, '23231', 'Hom'),
    (5, '2132315', 'Work')


SELECT *
FROM (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY ContactID ORDER BY PhoneType ASC) AS RowNum
    FROM #Test
    WHERE PhoneType IN ('Mob', 'Work', 'Hom')
) Sub 
WHERE RowNum = 1

如果您想先获得特定的手机类型,可以使用此选择语句进行ronum

SELECT *, ROW_NUMBER() OVER(PARTITION BY ContactID ORDER BY  CASE WHEN PhoneType = 'Mob' THEN 1 WHEN PhoneType = 'Work' THEN 2 WHEN PhoneType = 'Hom' THEN 3 END ASC) AS RowNum
FROM #Test
WHERE PhoneType IN ('Mob', 'Work', 'Hom')