假设我有三个表:
在安全测试表中,它包含从Cars表中对10辆汽车进行的每项安全测试的结果。最多有20个安全测试 - 显然是从SafetyTests表的select语句中获得的。然而,10辆汽车中的一些已经进行了所有20次测试,而其他汽车只有5次。
我想生产一个10 x 20矩阵,每辆车显示20个结果(即使他们没有20个安全测试结果)。如果尚未对汽车进行测试,则只显示测试名称,但值为零(或为空)。
我认为这将是SafetyTests表上的SELECT(以获取不同的测试ID列表)和LEFT JOIN到Cars和TestResults之间的JOIN组合,但问题是这返回了CAR ID为NULL缺少测试,因为与Car表没有匹配。
答案 0 :(得分:4)
您可以从汽车交叉连接到安全测试 - 然后将其连接到TestResults - 交叉连接确保您获得10 x 20矩阵,左连接为您提供结果
使用ISNULL或COALESCE用零替换结果集中的空值
e.g。
SELECT car.name, testresults.testname, isnull(testresults.result, 0) FROM
cars CROSS JOIN
safetytests
LEFT JOIN testresults on safetytests.testid = testresults.testid AND car.id = testresults.carid
像某人建议的那样,是一个非常好的网站
答案 1 :(得分:3)
如果我正确理解了这个问题,你想要一个像这样的10x20结果集:
CarID | Test1 | Test2 | .... | Test20
-------------------------------------------------------
1 | NULL | Fail | .... | true
2 | 2 | Pass | .... | false
为此,我将利用SQL-Server 2008的PIVOT
函数。
WITH Results AS
( SELECT cars.CarID,
TestName,
TestValue
FROM Cars
CROSS JOIN SafetyTests s
LEFT JOIN TestResults res
ON res.CarID = Cars.CarID
AND res.TestID = s.TestID
)
SELECT *
FROM Results
PIVOT
( MAX(TestValue)
FOR TestName IN ([TesT1], [Test2], [Test3], [Test4])
-- LIST ALL 20 TEST NAMES HERE
) pvt
这样做的缺点是你必须明确列出要转动的所有测试名称,否则它们不会显示为列,但是可以动态地执行此操作。下面与上面的查询基本完全相同,但我已动态生成所有列名列表并将其插入查询中。
DECLARE @SQL NVARCHAR(MAX) = ''
SELECT @SQL = @SQL + ',' + QUOTENAME(TestName)
FROM SafetyTests
SET @SQL = 'WITH Results AS
( SELECT Cars.CarID,
TestName,
TestValue
FROM Cars
CROSS JOIN SafetyTests s
LEFT JOIN TestResults res
ON res.CarID = Cars.CarID
AND res.TestID = s.TestID
)
SELECT *
FROM Results
PIVOT
( MAX(TestValue)
FOR TestName IN (' + STUFF(@SQL, 1, 1, '') + ')
) pvt'
EXECUTE SP_EXECUTESQL @SQL