我试图根据用户定义的层次结构选择值。 此层次结构未存储在系统上。
示例层次结构: 常规>专业>招聘
级别表(不一定顺序!)
+-----------+------------+
| ContactID | CategoryID |
+-----------+------------+
| 1 | Recruit |
| 1 | Major |
| 2 | Recruit |
| 3 | Major |
| 3 | General |
| 3 | Recruit |
+-----------+------------+
输出:
+-----------+------------+
| ContactID | CategoryID |
+-----------+------------+
| 1 | Major |
| 2 | Recruit |
| 3 | General |
+-----------+------------+
工作样本方法:
select ContactID,
case
when "General" in (select CategoryID from Level l1 where l.ContactID = l1.ContactID) then "General"
when "Major" in (select CategoryID from Level l1 where l.ContactID = l1.ContactID) then "Major"
when "Recruit" in (select CategoryID from Level l1 where l.ContactID = l1.ContactID) then "Recruit"
from Level l
有没有更有效的方法?实际数据在层次结构和许多记录中有30个级别。
使用Microsoft SQL Server,
谢谢
编辑:(感谢您的帮助!) 理想的解决方案还排除未包含在已定义层次结构中的记录。
例如,我们不需要显示用户5,因为他们没有有效的类别,用户4应该列为“招聘”。
+-----------+------------+
| ContactID | CategoryID |
+-----------+------------+
| 1 | Recruit |
| 1 | Major |
| 2 | Recruit |
| 3 | Major |
| 3 | General |
| 4 | Chef |
| 4 | Matron |
| 4 | Recruit |
| 5 | Paratrooper|
+-----------+------------+
结果
+-----------+------------+
| ContactID | CategoryID |
+-----------+------------+
| 1 | Major |
| 2 | Recruit |
| 3 | General |
| 4 | Recruit |
+-----------+------------+
答案 0 :(得分:1)
是的,有一个更简单的方法,在order by
子句中使用top 1 with ties
和row_number
:
SELECT TOP 1 WITH TIES ContactID, CategoryID
FROM TableName
ORDER BY ROW_NUMBER() OVER(
PARTITION BY ContactID
ORDER BY CASE CategoryID
WHEN 'General' THEN 1
WHEN 'Major' THEN 2
WHEN 'Recruit' THEN 3
ELSE
END
)
但是,由于实际数据在层次结构中具有30个级别,因此您不想为每个数据手动编写一个when
子句。
而是使用公用表表达式将层次结构的每个级别与数字配对,然后将表联接到此cte:
WITH CTESort AS
(
SELECT Category, Sort
FROM (VALUES
('General', 1),
('Major', 2),
('Recruit', 3)
-- and so on...
)V(Category, Sort)
)
SELECT TOP 1 WITH TIES ContactID, CategoryID
FROM TableName
JOIN CTESort
ON TableName.CategoryID = CTESort.Category
ORDER BY ROW_NUMBER() OVER(PARTITION BY ContactID ORDER BY CTESort.Sort)
答案 1 :(得分:0)
参见下文:
select 'General' < 'Major';
?column?
----------
t
(1 row)
select 'Major' < 'Recruit';
?column?
----------
t
(1 row)
所以'General' < 'Major' < 'Recruit'
是SQL的最简单方法:
select contractid,min(cateoryid) from level group by contractid order by contractid;
contractid | min
------------+---------
1 | Major
2 | Recruit
3 | General
(3 rows)