我试图弄清楚一个SQL查询,它会将记录从一个表分配或分配到另一个表。解释它的最好方法是通过一个人为的例子。
假设我有一张员工表,我想从颜色表中分配每种颜色。
我想确保颜色均匀分布,但员工没有任何属性可以预测他们会收到哪种颜色。
Sam
John
Jack
April
Sonny
Jill
Jane
Red
Green
Blue
Sam - Red
John - Green
Jack - Blue
April - Red
Sonny - Green
Jill - Blue
Jane - Red
如何在TSQL中构建此连接?
答案 0 :(得分:2)
我认为你想使用NTILE函数和一个参数,即颜色的数量。像这样:
;WITH Employees AS
(SELECT EmployeeName, NTILE(3) OVER (ORDER BY EmployeeName ASC) as ColorNumber FROM (values
('John'),('Jack'),('April'),('Sonny'),('Jill'),('Jane')) as e(EmployeeName)
),
Colors AS
(SELECT ColorName, ROW_NUMBER() OVER (ORDER BY ColorName ASC) as ColorNumber FROM (values
('Red'),('Green'),('Blue')) as c(ColorName)
)
SELECT EmployeeName, ColorName
FROM Employees
INNER JOIN Colors ON Employees.ColorNumber = Colors.ColorNumber
答案 1 :(得分:2)
我知道问题是关于SQLServer的,但对于那些对没有NTILE的解决方案感兴趣并只使用row_number的人来说:
-- (PostgreSQL syntax, but can be easly adapted to any DB)
with
-- "uses" a dummy colors table just for testing
colors as
(select 'Red' as color union all
select 'Green' union all
select 'Blue'
)
,
-- "uses" a dummy employees table just for testing
employees as
(select 'John' as employee union all
select 'Jack' union all
select 'April' union all
select 'Sonny' union all
select 'Jill' union all
select 'Jane'
)
,
-- here's the trick:
-- first we define a code_num as row_number for each color
c as
(select *,
row_number() over() as color_num
from colors
),
-- and then we define a code_num for each employee as
-- ((row_number-1) "mod" (colors' table count)) +1
e as
(select *,
(((row_number() over())-1) % (select count(*) from colors))+1 as color_num
from employees
)
-- get both tables joined by color_num
select e.employee,
c.color
from e
join c on c.color_num = e.color_num
<强>输出:强>
employee color
---------------
John Red
Jack Green
April Blue
Sonny Red
Jill Green
Jane Blue
答案 2 :(得分:0)
这可以通过使用NTILE
函数在MS SQL中使用ROW_NUMBER()
函数来实现。 NTILE
解决方案分发数据,但不像预期结果那样分配给定订单。
Sam - Red
John - Green
Jack - Blue
April - Red
Sonny - Green
Jill - Blue
Jane - Red
但是这个解决方案按预期提供输出。
DECLARE @Employees TABLE
(
Name VARCHAR(10)
)
INSERT INTO @Employees (Name)
VALUES ('Sam'), ('John'), ('Jack'), ('April'), ('Sonny'), ('Jill'), ('Jane');
DECLARE @Colors TABLE
(
Name VARCHAR(10)
)
INSERT INTO @Colors (Name)
VALUES ('Red'), ('Green'), ('Blue');
DECLARE @ColorCount INT
SELECT @ColorCount = COUNT(*) FROM @Colors
;WITH Employees(SNumber, Name) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS SNumber, Name
FROM @Employees
),
Colors(CNumber, Name) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS CNumber, Name
FROM @Colors
)
SELECT E.Name, C.Name FROM Employees E
INNER JOIN Colors C ON
CASE
WHEN (E.SNumber % @ColorCount) = 0
THEN @ColorCount
ELSE E.SNumber % @ColorCount
END = C.CNUmber
Sam - Red
April - Red
Jane - Red
John - Green
Sonny - Green
Jack - Blue
Jill - Blue