2015-06-25 102 views
6

构建我的第一个Microsoft Access SQL查询。这不应该这么难!
我有2个表:合并2个查询 - 在一个列名中获取并在另一个查询中使用结果

Data table AccessRights table

属于GroupA用户登录我想他只显示其GroupA被分配给那些Data表格的行和列,就像这样:

+--------+--------+--------+ 
| Group | Data3 | Data4 | 
+--------+--------+--------+ 
| GroupA | 9 | 4 | 
| GroupA | 1 | 5 | 
+--------+--------+--------+ 

我想这个愚蠢的选项:

SELECT (select Data from AccessRights where GroupA = "y") 
FROM Data 
WHERE Data.Group = "GroupA"; 
+0

那么,请你告诉我们哪些标准答案必须满足才能被你接受为答案?如果您需要运行VBA代码来解决问题,还是只与查询设计人员一起工作,是否可以接受? – Binarus

+0

我宁愿只在SQL中执行它。但是,如果不改变我的数据结构,这似乎是不可能的。所以VBA也不错。 – ZygD

+0

这个问题的根源在于模式。我不确定你想要解决什么问题,但是这个表格/栏目设计不好。这就是为什么你遇到SQL问题。如果您将“y”分配给AccessRights表的GroupA和GroupB列中的所有值,会发生什么情况?我认为你想建立的是一个基于角色的认证系统。你的表格会有所不同。 – itsben

回答

3

我使用此查询:

SELECT 
    Data.[Group], 
    IIf((SELECT GroupA FROM AccessRights WHERE Data = "Data1")="y",[Data1],Null) AS Data_1, 
    IIf((SELECT GroupA FROM AccessRights WHERE Data = "Data2")="y",[Data2],Null) AS Data_2, 
    IIf((SELECT GroupA FROM AccessRights WHERE Data = "Data3")="y",[Data3],Null) AS Data_3, 
    IIf((SELECT GroupA FROM AccessRights WHERE Data = "Data4")="y",[Data4],Null) AS Data_4 
FROM 
    Data 
WHERE 
    ((Data.[Group])="GroupA"); 

对于这个结果:

Group | Data_1 | Data_2 | Data_3 | Data_4 
--------+--------+--------+--------+-------- 
GroupA |  |  | 9  | 4 
GroupA |  |  | 1  | 5 

我只是隐藏Data1Data2值。


如果你真的想隐藏的列,您需要使用我创建一个VBA函数,将根据您的团给你的最终查询字符串VBA:

Function myQuery(groupName As String) As String 
    Dim strResult As String 
    Dim rs As Recordset 
    Dim i As Integer 

    strResult = "SELECT [DATA].[Group]" 

    Set rs = CurrentDb.OpenRecordset("SELECT [Data], [" & groupName & "] FROM AccessRights WHERE [" & groupName & "] = ""y""") 

    For i = 0 To rs.RecordCount 
     strResult = strResult & "," & rs.Fields("Data").Value 
     rs.MoveNext 
    Next i 

    strResult = strResult & " FROM [Data] WHERE ((Data.[Group])=""" & groupName & """)" 

    myQuery = strResult 
End Function 

例如; myQuery("GroupA")将是

SELECT [DATA].[Group],Data3,Data4 FROM [Data] WHERE ((Data.[Group])="GroupA") 
+0

当函数结束时,为什么不关闭记录集并将其设置为空?它是否自动关闭/设置为空? – ZygD

+0

@ZygD是的,它是一个局部变量。在结束之前关闭它是一个很好的观点。 –

+0

到目前为止,我最喜欢这个答案,因为它不需要我改变我的数据结构。 – ZygD

4

这可能会更好,只是转动您的数据表并添加一个名为数据的列。对访问权限也一样。

您的数据表将是这个样子:

Group, Data, Value 
Groupa,Data1,1 
Groupb,Data2,7 
... 

AccessRights是这样的:

Data, Group, Valid 
Data1, GroupA, Y 
Data2, GroupA, N 

然后你可以只连接两个表一起,过滤器需要。

Select * 
FROM Data D 
    JOIN AccessRights A 
    on D.data = A.data and D.Group = A.Group 
WHERE A.Valid = 'Y' 
     and D.Group = 'GroupA' 
+0

感谢您的建议。我想过摆动桌子,我仍然有这个选择。不过,我仍然相信应该有某种方式可以在不改变任何内容的情况下获得结果。我仍然认为任何RDBMS都是灵活的,我不想失去这个信念,这很容易...... :) – ZygD

+3

这个答案显示了RDBMS *如何*灵活。你的方式正在与关系数据库的工作方式作斗争。访问在混合数据和表示方面有点更宽容,但通常使用表结构,您可以选择行来整理表示部分中的动态列。请注意,这种方法的缺点是所有数据必须具有相同的类型。 – LoztInSpace

0

好吧最后这里是你需要的结果。 这个解决方案的好处是你不需要运行额外的脚本,也只需要传递组名作为参数,它将只返回你需要的列。请享用。 :)

declare @aa varchar (200) = '' 
declare @sql varchar(500) = '' 
declare @groupinfo varchar(100) = 'GroupA' 

Select @aa = coalesce (case when @aa = '' then Data else @aa + ',' + Data end ,'') 
    from [AccessRights] where GroupA = 'y' 

Set @sql = 'Select [Group],' + @aa + ' from Data where [Group] = ' + '''' + @groupinfo + '''' 
Exec(@sql) 

+--------+--------+--------+ 
| Group | Data3 | Data4 | 
+--------+--------+--------+ 
| GroupA | 9 | 4 | 
| GroupA | 1 | 5 | 
+--------+--------+--------+ 
+1

这个答案使用T-SQL,它将在Microsoft SQL Server中工作,但在Access中不起作用。 –

+0

很高兴知道在SQL Server上会有解决方案:) – ZygD

1

@ZygD,这里的模式:

USER 
user_id int primary key auto_increment 
user_name varchar(100) 
password varchar(100) 

GROUP 
group_id int primary key auto_increment 
group_name varchar(100) 

DATA 
data_id int primary key auto_increment 
data_name varchar(100) 

USER_GROUP 
user_id int 
group_id int 


GROUP_DATA 
group_id 
data_id 

我会解释。首先你定义你的“对象类型”。你有一个用户,组和你称为数据。除了使用另一个单词而不是DATA,可能是一个好主意。使用类似ITEM的东西,甚至是DATAITEM。对于这个例子,我将使用DATA。好吧,所以这些表中的每一个都有一个整数值,因为它是主键。主键是表中记录的唯一标识符,并且它自动递增。你可以在Access中进行设置。

既然您有三个对象类型表,您需要称为“连接表”来描述“对象类型”表之间的关系。 USER_GROUP表中说用户可以属于一个或多个组。例如,如果用户1属于组1和组2,那么USER_GROUP表中将有两条记录来描述这些关系。第一行是1,1,第二行是1,2。

GROUP_DATA表格描述GROUP和DATA之间的关系。例如,组1可以访问数据2和数据3.同样,您将在GROUP_DATA表中有两行来描述这些关系。第一行是1,2,第二行是1,3。现在

,因为用户1属于第1组,那么用户1将有数据2和3。你的SQL然后变得简化访问:

// Authenticate the user with user_name and password: 
select @user_id = a.user_id from user a where a.user_name = @user_name and a.password = @password 

// Get DATA by user_id 
select c.data_id, c.data_name from user a join group b on a.user_id = b.user_id join data c on b.data_id = c.data_id where a.user_id = @user_id 
+0

谢谢你的答案。太糟糕了,我没有太多时间详细研究它。我非常感谢,稍后我会回头看看! – ZygD

相关问题