我有两个表:#tmpParams,列出了29种Disability和Grade的组合。第二个表#tmpSource包含许多具有StudentID,Disability和Grade的学生。我需要从#tmpSource中选择29个随机行,通过Disability and Grade加入#tmpParams。
换句话说,有人向我递交了29名学生(残疾和年级)的参数列表,他们希望29名来自#tmpSource的随机学生,包括StudentID,在这两个领域匹配。
这是DDL:
IF OBJECT_ID('tempdb..#tmpParams') IS NOT NULL
BEGIN
DROP TABLE #tmpParams
END
GO
IF OBJECT_ID('tempdb..#tmpSource') IS NOT NULL
BEGIN
DROP TABLE #tmpSource
END
GO
/* Create parameter table */
CREATE TABLE #tmpParams
(
Disability varchar(10)
,Grade varchar(10)
)
GO
/* populate it */
INSERT INTO #tmpParams
(Disability, Grade)
SELECT '13 - AUT' ,'Grade 1' UNION ALL
SELECT '08 - SL' ,'Grade 1' UNION ALL
SELECT '11 - PSD' ,'Grade 1' UNION ALL
SELECT '04 - SLD' ,'Grade 2' UNION ALL
SELECT '04 - SLD' ,'Grade 2' UNION ALL
SELECT '08 - SL' ,'Grade 2' UNION ALL
SELECT '08 - SL' ,'Grade 2' UNION ALL
SELECT '08 - SL' ,'Grade 2' UNION ALL
SELECT '14 - TBI' ,'Grade 2' UNION ALL
SELECT '07 - PD' ,'Grade 2' UNION ALL
SELECT '08 - SL' ,'Grade 3' UNION ALL
SELECT '08 - SL' ,'Grade 3' UNION ALL
SELECT '08 - SL' ,'Grade 3' UNION ALL
SELECT '08 - SL' ,'Grade 3' UNION ALL
SELECT '08 - SL' ,'Grade 3' UNION ALL
SELECT '07 - PD' ,'Grade 3' UNION ALL
SELECT '04 - SLD' ,'Grade 4' UNION ALL
SELECT '04 - SLD' ,'Grade 4' UNION ALL
SELECT '08 - SL' ,'Grade 4' UNION ALL
SELECT '08 - SL' ,'Grade 4' UNION ALL
SELECT '08 - SL' ,'Grade 4' UNION ALL
SELECT '08 - SL' ,'Grade 4' UNION ALL
SELECT '08 - SL' ,'Grade 4' UNION ALL
SELECT '04 - SLD' ,'Grade 5' UNION ALL
SELECT '04 - SLD' ,'Grade 5' UNION ALL
SELECT '04 - SLD' ,'Grade 5' UNION ALL
SELECT '04 - SLD' ,'Grade 5' UNION ALL
SELECT '08 - SL' ,'Grade 5' UNION ALL
SELECT '08 - SL' ,'Grade 5';
GO
/* Create table to hold source */
CREATE TABLE #tmpSource
(
StudentID int
,Disability varchar(10)
,Grade varchar(10)
)
GO
INSERT INTO #tmpSource
(StudentID, Disability, Grade)
SELECT '3', '04 - SLD', 'Grade 2' UNION ALL
SELECT '31', '04 - SLD', 'Grade 2' UNION ALL
SELECT '39', '04 - SLD', 'Grade 2' UNION ALL
SELECT '46', '04 - SLD', 'Grade 2' UNION ALL
SELECT '10', '04 - SLD', 'Grade 4' UNION ALL
SELECT '13', '04 - SLD', 'Grade 4' UNION ALL
SELECT '25', '04 - SLD', 'Grade 4' UNION ALL
SELECT '33', '04 - SLD', 'Grade 4' UNION ALL
SELECT '57', '04 - SLD', 'Grade 4' UNION ALL
SELECT '60', '04 - SLD', 'Grade 4' UNION ALL
SELECT '8', '04 - SLD', 'Grade 5' UNION ALL
SELECT '19', '04 - SLD', 'Grade 5' UNION ALL
SELECT '23', '04 - SLD', 'Grade 5' UNION ALL
SELECT '51', '04 - SLD', 'Grade 5' UNION ALL
SELECT '55', '04 - SLD', 'Grade 5' UNION ALL
SELECT '16', '07 - PD', 'Grade 2' UNION ALL
SELECT '28', '07 - PD', 'Grade 2' UNION ALL
SELECT '36', '07 - PD', 'Grade 2' UNION ALL
SELECT '43', '07 - PD', 'Grade 2' UNION ALL
SELECT '11', '07 - PD', 'Grade 3' UNION ALL
SELECT '14', '07 - PD', 'Grade 3' UNION ALL
SELECT '26', '07 - PD', 'Grade 3' UNION ALL
SELECT '34', '07 - PD', 'Grade 3' UNION ALL
SELECT '58', '07 - PD', 'Grade 3' UNION ALL
SELECT '61', '07 - PD', 'Grade 3' UNION ALL
SELECT '5', '08 - SL', 'Grade 1' UNION ALL
SELECT '21', '08 - SL', 'Grade 1' UNION ALL
SELECT '41', '08 - SL', 'Grade 1' UNION ALL
SELECT '48', '08 - SL', 'Grade 1' UNION ALL
SELECT '2', '08 - SL', 'Grade 2' UNION ALL
SELECT '30', '08 - SL', 'Grade 2' UNION ALL
SELECT '38', '08 - SL', 'Grade 2' UNION ALL
SELECT '45', '08 - SL', 'Grade 2' UNION ALL
SELECT '12', '08 - SL', 'Grade 3' UNION ALL
SELECT '15', '08 - SL', 'Grade 3' UNION ALL
SELECT '27', '08 - SL', 'Grade 3' UNION ALL
SELECT '35', '08 - SL', 'Grade 3' UNION ALL
SELECT '59', '08 - SL', 'Grade 3' UNION ALL
SELECT '62', '08 - SL', 'Grade 3' UNION ALL
SELECT '9', '08 - SL', 'Grade 4' UNION ALL
SELECT '20', '08 - SL', 'Grade 4' UNION ALL
SELECT '24', '08 - SL', 'Grade 4' UNION ALL
SELECT '52', '08 - SL', 'Grade 4' UNION ALL
SELECT '56', '08 - SL', 'Grade 4' UNION ALL
SELECT '7', '08 - SL', 'Grade 5' UNION ALL
SELECT '18', '08 - SL', 'Grade 5' UNION ALL
SELECT '22', '08 - SL', 'Grade 5' UNION ALL
SELECT '50', '08 - SL', 'Grade 5' UNION ALL
SELECT '54', '08 - SL', 'Grade 5' UNION ALL
SELECT '4', '11 - PSD', 'Grade 1' UNION ALL
SELECT '32', '11 - PSD', 'Grade 1' UNION ALL
SELECT '40', '11 - PSD', 'Grade 1' UNION ALL
SELECT '47', '11 - PSD', 'Grade 1' UNION ALL
SELECT '6', '13 - AUT', 'Grade 1' UNION ALL
SELECT '17', '13 - AUT', 'Grade 1' UNION ALL
SELECT '42', '13 - AUT', 'Grade 1' UNION ALL
SELECT '49', '13 - AUT', 'Grade 1' UNION ALL
SELECT '53', '13 - AUT', 'Grade 1' UNION ALL
SELECT '1', '14 - TBI', 'Grade 2' UNION ALL
SELECT '29', '14 - TBI', 'Grade 2' UNION ALL
SELECT '37', '14 - TBI', 'Grade 2' UNION ALL
SELECT '44', '14 - TBI', 'Grade 2';
GO
将29名学生填入#tmpParams,将62名学生填入#tmpSource。当然,我的现实场景要复杂得多。
我可以轻松地从#tmpSource获得29名随机学生......但是我如何加入#tmpParams以获得在两个领域匹配的29名学生?
SELECT TOP 29
TS.StudentID
,TS.Disability
,TS.Grade
FROM #tmpSource AS TS
ORDER BY NEWID();
GO
一如既往,感谢您的帮助,如果我能澄清某些内容或让您更容易阅读,请告诉我。
答案 0 :(得分:3)
我可能会遗漏一些东西,但为什么不呢
SELECT TOP 29 TS.StudentID,
TS.Disability,
TS.Grade
FROM #tmpParams P
JOIN #tmpSource TS
ON TS.Disability = P.Disability
AND TS.Grade = P.Grade
ORDER BY NEWID()
你想要这个吗?
SELECT TS.StudentID,
TS.Disability,
TS.Grade
FROM #tmpParams P
CROSS APPLY (SELECT TOP 1 *
FROM #tmpSource TS
WHERE TS.Disability = P.Disability
AND TS.Grade = P.Grade
ORDER BY NEWID()) TS
你想要这个吗?
;WITH T1
AS (SELECT *,
Row_number() OVER (PARTITION BY Disability, Grade ORDER BY Newid()) RN
FROM #tmpSource),
T2
AS (SELECT Disability,
Grade,
Row_number() OVER (PARTITION BY Disability, Grade
ORDER BY (SELECT 0)) AS RN
FROM #tmpParams)
SELECT T1.Disability,
T1.Grade,
T1.StudentID
FROM T1
JOIN T2
ON T1.Disability = T2.Disability
AND T2.Grade = T1.Grade
AND T1.RN = T2.RN
答案 1 :(得分:2)
with sample as
(
select p.disability, p.grade, count(*) as numOfSamples from #tmpParams P
group by p.disability, p.grade
),
rownumedStuds as
(
select std.id, std.disability, std.grade, row_number() over (partition by std.disability, std.grade order by newID()) num
)
select a.id,a.disability, a.grade
from sample b
inner join rownumedStuds a on a.grade = b.grade and a.disability = b.disability
where num <= numOfSamples
基本上它确实计算了桶的数量和匹配的数量,然后随机化每个组(如果这是性能很重你可以循环加入它只有rownumedStuds中需要的仅用于随机化你需要的组的类别。
实际选择我希望非常简单
问候 路加
答案 2 :(得分:0)
我可能已经想到了这一点,虽然看起来并不优雅:
/* Add identity column to #tmpParams */
ALTER TABLE #tmpParams ADD ID INT IDENTITY (1,1)
/* drop #tmpResults if exists */
IF OBJECT_ID('tempdb..#tmpResults') IS NOT NULL
BEGIN
DROP TABLE #tmpResults
END
GO
/* Create table to hold results */
CREATE TABLE #tmpResults
(
StudentID int
,Disability varchar(10)
,Grade varchar(10)
)
GO
DECLARE @i AS INT; -- set variable to parse through
SET @i = 1
WHILE @i <= (SELECT MAX(ID) FROM #tmpParams) -- Max number in table
BEGIN
INSERT INTO #tmpResults
SELECT TOP 1
TS.StudentID
,TS.Disability
,TS.Grade
FROM #tmpSource AS TS
JOIN #tmpParams AS TP
ON TS.Disability = TP.Disability
AND TS.Grade = TP.Grade
WHERE TP.ID = @i
AND TS.StudentID NOT IN (SELECT StudentID FROM #tmpResults) -- so no duplicates
ORDER BY NEWID()
SET @i = @i + 1
END;
GO
感谢你的帮助,马丁,它让我走上正轨。