0

将 MS access 2010 与 SQL Server 2005 的链接表一起使用。链接表有 5 列:

PName - STRING
OName - STRING
FName - STRING  
Readable - BOOLEAN  
Editable - BOOLEAN  

样本数据:

PName   FName                readable   editable
UK      Case.First_Name         0       0
UK      Case.Last_Name          0       0
UK      Case.Middle_Initial     0       0
UK      Case.Phone_Number       0       0
UK      Case.Username           -1      -1
USA     Case.First_Name         0       0
USA     Case.Last_Name          0       0
USA     Case.Middle_Initial     0       0
USA     Case.Phone_Number       0       0
USA     Case.Username           -1      -1

希望创建一个查询,该查询将按 PName 返回所有 FName 的列表,但仅在所有 PName 的 Readable 值不同或所有 PName 的 Editable 值不同时才显示 FName。

示例输出:

                      UK           USA
                   Edit|Read    EDIT|Read
Case.First_Name    T   |  T       F | T
Case.UserName      F   |  F       F | T

在上面,“Case.First_Name”可由英国编辑,但不能由美国编辑,因此我希望看到这一行

Case.UserName 英国不可读,但美国可读,因此我想看到这一行

不应该输出的内容:

                      UK           USA
                   Edit|Read    EDIT|Read
Case.First_Name    T   |  T       T | T
Case.UserName      F   |  F       F | F

上述两行对英国和美国都具有相同的可读性和可编辑性权限,因此我不想看到这些行。

下面的查询将为我提供我需要的原始数据,然后我可以将其转换为数据透视表:

SELECT PName, FName, Readable, Editable
FROM ProfileFLS
WHERE PName Like "U*";

然后将其导出到 Excel 并使用 If 语句。

请注意,配置文件的数量是动态的。

谢谢你的帮助

最新的 SQL:

SQL如下,我也试过把="True"改成0

TRANSFORM Sum(IIf(dbo_ProfileFLS.readable="TRUE","Read_True","Read_False")) AS Readable
SELECT dbo_ProfileFLS.fieldname
FROM dbo_ProfileFLS
WHERE (((dbo_ProfileFLS.objectname)="Case") AND ((dbo_ProfileFLS.Profile) Like "UK*"))
GROUP BY dbo_ProfileFLS.fieldname, dbo_ProfileFLS.readable
PIVOT dbo_ProfileFLS.Profile;
4

2 回答 2

2

感谢您编辑您的问题。事情现在清楚多了。

让我们从调整您的样本数据开始,以便获得一些实际结果。

PName   FName               readable    editable
UK      Case.First_Name     0           -1
UK      Case.Last_Name      0           0
UK      Case.Middle_Initial 0           0
UK      Case.Phone_Number   0           0
UK      Case.Username       -1          -1
USA     Case.First_Name     0           0
USA     Case.Last_Name      0           0
USA     Case.Middle_Initial -1          0
USA     Case.Phone_Number   0           0
USA     Case.Username       -1          -1
Canada  Case.First_Name     0           0
Canada  Case.Last_Name      0           -1
Canada  Case.Middle_Initial 0           0
Canada  Case.Phone_Number   0           0
Canada  Case.Username       0           0

现在考虑以下查询。这是一个自联接,在 [FName] 上查找匹配项,在 [readable] OR [editable] 上查找不匹配项:

SELECT p1.FName, 
    p1.PName AS PName1, p1.readable AS read1, p1.editable AS edit1,
    p2.PName AS PName2, p2.readable AS read2, p2.editable AS edit2
FROM permissionsTbl p1 INNER JOIN permissionsTbl p2
    ON p1.FName=p2.FName 
        AND (p1.readable<>p2.readable OR p1.editable<>p2.editable)
ORDER BY 1, 2 ;

它返回

FName               PName1  read1   edit1   PName2  read2   edit2
Case.First_Name     Canada  0       0       UK      0       -1
Case.First_Name     UK      0       -1      Canada  0       0
Case.First_Name     UK      0       -1      USA     0       0
Case.First_Name     USA     0       0       UK      0       -1
Case.Last_Name      Canada  0       -1      USA     0       0
Case.Last_Name      Canada  0       -1      UK      0       0
Case.Last_Name      UK      0       0       Canada  0       -1
Case.Last_Name      USA     0       0       Canada  0       -1
Case.Middle_Initial Canada  0       0       USA     -1      0
Case.Middle_Initial UK      0       0       USA     -1      0
Case.Middle_Initial USA     -1      0       UK      0       0
Case.Middle_Initial USA     -1      0       Canada  0       0
Case.Username       Canada  0       0       USA     -1      -1
Case.Username       Canada  0       0       UK      -1      -1
Case.Username       UK      -1      -1      Canada  0       0
Case.Username       USA     -1      -1      Canada  0       0

并向我们​​展示了读取或编辑权限不匹配的每种情况。

现在我们将对其进行调整,为我们提供上面列表中出现的 [FName] 值的 DISTINCT 列表......

SELECT DISTINCT p1.FName 
FROM permissionsTbl p1 INNER JOIN permissionsTbl p2
    ON p1.FName=p2.FName 
        AND (p1.readable<>p2.readable OR p1.editable<>p2.editable) ;

...并将其用作子查询以从原始表中提取那些 FName 行

SELECT * FROM permissionsTbl
WHERE FName IN
(
    SELECT DISTINCT p1.FName 
    FROM permissionsTbl p1 INNER JOIN permissionsTbl p2
        ON p1.FName=p2.FName 
            AND (p1.readable<>p2.readable OR p1.editable<>p2.editable)
) ;

...返回...

PName   FName               readable    editable
UK      Case.First_Name     0           -1
UK      Case.Last_Name      0           0
UK      Case.Middle_Initial 0           0
UK      Case.Username       -1          -1
USA     Case.First_Name     0           0
USA     Case.Last_Name      0           0
USA     Case.Middle_Initial -1          0
USA     Case.Username       -1          -1
Canada  Case.First_Name     0           0
Canada  Case.Last_Name      0           -1
Canada  Case.Middle_Initial 0           0
Canada  Case.Username       0           0

...并可用于为您的下游流程提供原料。

于 2013-04-04T17:11:12.033 回答
0

您可以使用 MS Access 向导创建交叉表查询,也可以使用 PIVOT 创建 SQL-Passthrough 查询以让 SQL Server 进行处理。

编辑:根据修改后的问题添加了以下内容

您也许可以在不使用交叉表的情况下逃脱。这取决于您的查询需要多么灵活,或者您是否可以动态构建查询。对于上面的英国/美国示例,您可以使用:

SELECT dbo_ProfileFLS.FName,
       dbo_ProfileFLS.Readable AS [UK Read], 
       dbo_ProfileFLS.Editable AS [UK Edit],
       dbo_ProfileFLS_1.Readable AS [USA Read],
       dbo_ProfileFLS_1.Editable AS [USA Edit]
FROM   dbo_ProfileFLS
INNER JOIN dbo_ProfileFLS AS dbo_ProfileFLS_1
ON     dbo_ProfileFLS.FName = dbo_ProfileFLS_1.FName
WHERE  dbo_ProfileFLS.PName="UK"
  AND  dbo_ProfileFLS_1.PName="USA" 
  AND  (dbo_ProfileFLS.Readable<>[dbo_ProfileFLS_1].[Readable]
       OR dbo_ProfileFLS.Editable<>[dbo_ProfileFLS_1].[Editable]);

如果您真的想使用交叉表,那么问题是您只能使用一列作为值(正如您已经看到的那样)。您可以通过连接 Readable 和 Editable 字段来克服这个问题。由于交叉表使用 Group By 但实际上您想要普通值,因此您需要首先使用聚合函数。例如:

TRANSFORM First(Readable & " | " & Editable) AS ReadEdit
SELECT dbo_ProfileFLS.FName
FROM dbo_ProfileFLS
GROUP BY dbo_ProfileFLS.FName
PIVOT dbo_ProfileFLS.PName & " Read | Edit";

当然,这个查询需要完整的表。要仅获取正确的值,您需要将第一个查询的变体用作过滤器:

SELECT dbo_ProfileFLS.ID AS UK_ID,
       dbo_ProfileFLS_1.ID AS USA_ID
FROM   dbo_ProfileFLS
INNER JOIN dbo_ProfileFLS AS dbo_ProfileFLS_1 
ON     dbo_ProfileFLS.FName = dbo_ProfileFLS_1.FName
WHERE  dbo_ProfileFLS.PName="UK"
  AND  dbo_ProfileFLS_1.PName="USA" 
  AND  (dbo_ProfileFLS.Readable<>[dbo_ProfileFLS_1].[Readable]
       OR dbo_ProfileFLS.Editable<>[dbo_ProfileFLS_1].[Editable]);

如果将其命名为 crosstabFilter,则将其与 dbo_ProfileFLS 交叉连接并使用条件:

WHERE crosstabFilter.UK_ID=ID OR crosstabFilter.USA_ID=ID
于 2013-04-04T14:26:45.427 回答