我试图围绕如何使用数据透视表来处理我需要的查询。我有3个数据库表。显示相关列:
TableA: Columns = pName
TableB: Columns = GroupName, GroupID
TableC: Columns = pName, GroupID
TableA contains a list of names (John, Joe, Jack, Jane)
TableB contains a list of groups with an ID#. (Soccer|1, Hockey|2, Basketball|3)
TableC contains a list of the names and the group they belong to (John|1, John|3, Joe|2, Jack|1, Jack|2, Jack|3, Jane|3)
我需要使用SQL查询创建一个类似于网格视图的矩阵,该查询将返回TableA(Y轴)中所有名称的列表以及所有可能组(X轴)的列表。如果单元格属于该组,则单元格值将为true或false。
任何帮助将不胜感激。我无法找到有帮助的现有答案。
答案 0 :(得分:3)
您可以像这样尝试
我在这里设置MCVE,请在下一个问题中尝试创建这个...
DECLARE @Name TABLE (pName VARCHAR(100));
INSERT INTO @Name VALUES('John'),('Joe'),('Jack'),('Jane');
DECLARE @Group TABLE(gName VARCHAR(100),gID INT);
INSERT INTO @Group VALUES ('Soccer',1),('Hockey',2),('Basketball',3);
DECLARE @map TABLE(pName VARCHAR(100),gID INT);
INSERT INTO @map VALUES
('John',1),('John',3)
,('Joe',2)
,('Jack',1),('Jack',2),('Jack',3)
,('Jane',3);
此查询将收集值并执行PIVOT
SELECT p.*
FROM
(
SELECT n.pName
,g.gName
,'x' AS IsInGroup
FROM @map AS m
INNER JOIN @Name AS n ON m.pName=n.pName
INNER JOIN @Group AS g ON m.gID=g.gID
) AS x
PIVOT
(
MAX(IsInGroup) FOR gName IN(Soccer,Hockey,Basketball)
) as p
结果就是这样。
pName Soccer Hockey Basketball
Jack x x x
Jane NULL NULL x
Joe NULL x NULL
John x NULL x
一些提示:
1
和0
代替x
,因为SQL Server不知道真实布尔 pID
。永远不要在真实数据上加入表格(除非它是独特且不可更改的东西[这意味着永远不会] !!!)如果您想要一个动态处理任何数量的群组的查询。但请注意,您在 ad-hoc-SQL 中失去了使用此功能的机会,例如VIEW
或inline TVF
,这是一个非常大的反向... < / p>
CREATE TABLE #Name(pName VARCHAR(100));
INSERT INTO #Name VALUES('John'),('Joe'),('Jack'),('Jane');
CREATE TABLE #Group(gName VARCHAR(100),gID INT);
INSERT INTO #Group VALUES ('Soccer',1),('Hockey',2),('Basketball',3);
CREATE TABLE #map(pName VARCHAR(100),gID INT);
INSERT INTO #map VALUES
('John',1),('John',3)
,('Joe',2)
,('Jack',1),('Jack',2),('Jack',3)
,('Jane',3);
DECLARE @ListOfGroups VARCHAR(MAX)=
(
STUFF
(
(
SELECT DISTINCT ',' + QUOTENAME(gName)
FROM #Group
FOR XML PATH('')
),1,1,''
)
);
DECLARE @sql VARCHAR(MAX)=
(
'SELECT p.*
FROM
(
SELECT n.pName
,g.gName
,''x'' AS IsInGroup
FROM #map AS m
INNER JOIN #Name AS n ON m.pName=n.pName
INNER JOIN #Group AS g ON m.gID=g.gID
) AS x
PIVOT
(
MAX(IsInGroup) FOR gName IN(' + @ListOfGroups + ')
) as p');
EXEC(@sql);
GO
DROP TABLE #map;
DROP TABLE #Group;
DROP TABLE #Name;
答案 1 :(得分:0)
我怀疑如果添加类别,保持枢轴更新可能会很费力。或许我只是喜欢Excel(如果你忽略了一个主要优势)。假设您有Office 365,以下方法也可能会有所帮助。
我根据上面看到的代码使用3个CREATE TABLE语句和3个INSERT语句添加了三个表。 (解决方案使用临时表来插入特定值,但我相信您已经在三个表中拥有了数据,称为TableA,TableB,TableC)。
CREATE TABLE TestName (pName VARCHAR(100));
INSERT INTO TestName VALUES('John'),('Joe'),('Jack'),('Jane');
CREATE TABLE TestGroup (gName VARCHAR(100),gID INT);
INSERT INTO TestGroup VALUES ('Soccer',1),('Hockey',2),('Basketball',3);
CREATE TABLE Testmap (pName VARCHAR(100),gID INT);
INSERT INTO Testmap VALUES
('John',1),('John',3)
,('Joe',2)
,('Jack',1),('Jack',2),('Jack',3)
,('Jane',3);
然后,在MS Excel中,我添加了(可能有一个较短的序列,但我仍然在探索)这三个表作为来自数据库&gt;的查询。 sql server数据库。添加它们之后,我将所有三个添加到数据模型中(如果你问我可以详细说明)。
然后我从功能区插入了数据透视表,选择了外部数据源,但打开了表格选项卡(而不是连接选项卡),找到我的数据模型(我的列表是最重要的),然后点击了打开。在某些时候,Excel提示我创建表之间的关系,它为我自动生成它们做得很好。
经过小调整后,我的数据透视表就像这样(我也可以要求Excel将数据显示为数据透视图)。 Pivot showing groups as columns and names as rows.
优点是,如果列表(组)发生更改,则不必在SQL中重新访问PIVOT代码。正如我想其他人提到的那样,考虑使用id作为pName,或者另一种方法来确保如果你有两个名叫John或Jack的人,你第二天就不会被卡住。
在Excel中,您可以选择何时刷新数据(或数据透视),刷新后,将添加和计算任何其他类别。