繁体   English   中英

SQL - MS Access - if 语句

[英]SQL - MS Access - if statement

我有下表:

Table1
Color  Room type
Black  Large
White  Large
White  Small
Black  Medium
Black  Small

我想运行一个查询:

  • 如果数据显示大房间的 colors 比黑色更频繁地出现白色,那么结果将是白色
  • 如果数据显示黑色比白色更频繁地出现,那么结果将是黑色。
  • 如果数据显示黑方出现的次数与白方相同,则结果将无法识别。

请注意,我的查询比这更复杂,它有其他列和许多表,但我只想添加指定大房间主要是白色还是黑色的列。

对于所有类型的房间:

SELECT RoomType
     , Count( IIF(Color="White",1,NULL) ) AS CountWhite
     , Count( IIF(Color="Black",1,NULL) ) AS CountBlack
     , IIF(   Count( IIF(Color="White",1,NULL) )
            > Count( IIF(Color="Black",1,NULL) ) 
                , "White"
       , IIF(   Count( IIF(Color="White",1,NULL) )
              = Count( IIF(Color="Black",1,NULL) ) 
                , NULL
                , "Black"
            )
          )
       AS Result
FROM Rooms
GROUP BY RoomType

仅适用于“大”房间:

SELECT IIF(   Count( IIF(Color="White",1,NULL) )
            > Count( IIF(Color="Black",1,NULL) ) 
                , "White"
       , IIF(   Count( IIF(Color="White",1,NULL) )
              = Count( IIF(Color="Black",1,NULL) ) 
                , NULL
                , "Black"
            )
          )
       AS Result
FROM Rooms
WHERE RoomType = "Large"

由于您的问题尚不清楚,因此我们必须对您的目标进行一些相当全面的猜测。 如果你的桌子真的更像:

Rooms
RoomID Color  Room type
  1    Black  Large
  2    White  Large
  3    White  Small
  4    Black  Medium
  5    Black  Small
  6    Black  Large
  7    White  Large
  8    White  Small
  9    White  Large
 10    White  Large

如果您想知道三种尺寸中的每一种是否有更多的黑色或白色房间,并且您指定“有相同数量的黑色和白色房间”(灰色?),以及 MS Access 是否可以使用它语法,那么也许:

每种尺寸每种颜色的房间数量:

SELECT [Room type] AS RoomType, Color, COUNT(*) AS RoomCount
  FROM Rooms
 GROUP BY RoomType, Color

自联接此结果以将黑白计数放入单个表中:

SELECT NVL(Black.RoomType, White.RoomType) AS RoomType,
       NVL(WhiteCount, 0) AS WhiteCount,
       NVL(BlackCount, 0) AS BlackCount
  FROM (SELECT [Room type] AS RoomType, COUNT(*) AS WhiteCount
          FROM Rooms
         WHERE Color = 'White'
         GROUP BY RoomType
       ) AS White
  FULL OUTER JOIN
       (SELECT [Room type] AS RoomType, COUNT(*) AS BlackCount
          FROM Rooms
         WHERE Color = 'Black'
         GROUP BY RoomType
       ) AS Black
       ON Black.RoomType = White.RoomType

(我不知道 MS Access 是否支持 FULL OUTER JOIN。如果没有,你必须更加努力。同样,我没有检查它是否支持 NVL - 也许它支持 COALESCE。)

这将为您提供一系列行,每个房间类型一个,带有 WhiteCount 和 BlackCount。

现在您只需要对其进行后期处理即可为您提供所需的信息 - 如果我的猜测是合理的。


编辑:必须在 RoomType 上使用 NVL() 或等效项并包含表别名; 现在使用 IBM Informix Dynamic Server 11.70.FC1 在 MacOS X 10.6.7 上测试并生成正确答案:

Roomtype   Whitecount   Blackcount
Large      4            2
Small      2            1
Medium     0            1

如果 MS Access 不支持 FULL OUTER JOIN,则查询会非常混乱。 它是否支持 LEFT 和 RIGHT (OUTER) JOIN? 希望如此,因为这样您就可以使用它(已更改为假设列名称为 Rooms.RoomType(名称中没有空格):

SELECT NVL(White.RoomType, Black.RoomType) AS RoomType,
       NVL(WhiteCount, 0) AS WhiteCount,
       NVL(BlackCount, 0) AS BlackCount
  FROM (SELECT RoomType AS RoomType, COUNT(*) AS WhiteCount
          FROM Rooms
         WHERE Color = 'White'
         GROUP BY RoomType
       ) AS White
  LEFT OUTER JOIN
       (SELECT RoomType AS RoomType, COUNT(*) AS BlackCount
          FROM Rooms
         WHERE Color = 'Black'
         GROUP BY RoomType
       ) AS Black
       ON Black.RoomType = White.RoomType
UNION
SELECT NVL(White.RoomType, Black.RoomType) AS RoomType,
       NVL(WhiteCount, 0) AS WhiteCount,
       NVL(BlackCount, 0) AS BlackCount
  FROM (SELECT RoomType AS RoomType, COUNT(*) AS WhiteCount
          FROM Rooms
         WHERE Color = 'White'
         GROUP BY RoomType
       ) AS White
  RIGHT OUTER JOIN
       (SELECT RoomType AS RoomType, COUNT(*) AS BlackCount
          FROM Rooms
         WHERE Color = 'Black'
         GROUP BY RoomType
       ) AS Black
       ON Black.RoomType = White.RoomType;

此公式依赖于 UNION 删除重复行。 给定测试数据,它会产生相同的结果。 您可以通过在 UNION 前半部分(而不是 NVL 表达式)的主选择列表中使用 White.RoomType 和在后半部分中使用 Black.RoomType 来稍微压缩它。

如果 MS Access 不支持任何外部联接,那么 (a) 是时候升级到真正的 DBMS 了,并且 (b) 让我知道,我们将制定出长期的 3 路 UNION 方式来完成同样的工作.

由于这是 Access(ACE、Jet 等),我们可能需要通过VIEW使用中间结果集(保存的查询对象、querydefs 等):

CREATE VIEW Table1ColorTallies
(
 Color, tally
)
AS 
SELECT Color, COUNT(*) AS tally
  FROM Table1
 GROUP 
    BY Color;

CREATE VIEW Table1ColorsWithMaxTallies
(
 Color
)
AS 
SELECT T1.Color
  FROM Table1ColorTallies AS T1
 WHERE T1.tally = (
                   SELECT MAX(T2.tally)
                     FROM Table1ColorTallies AS T2
                  );

使用VIEW获得所需的结果:

SELECT Color
  FROM Table1ColorsWithMaxTallies
 WHERE 1 = (
            SELECT COUNT(*)
              FROM Table1ColorsWithMaxTallies AS T2
           );

注意上面的CREATE VIEW SQL DDL 必须在ANSI-92 查询模式下单独执行。 或者,以通常的方式使用 Access UI(DAO 等)将它们创建为已保存的查询对象(querydefs 等)。


这是一些 VBA 在您的临时文件夹中创建一个名为 DropMe.mdb 的新数据库,使用示例数据创建Table1 ,然后创建我建议的VIEW并在消息框中显示我建议的查询的结果。 使用 ADO 但不需要引用(使用后期绑定)。 只需粘贴任何 VBA 标准代码模块(例如使用 Excel)并运行。 我认为它可以很好地扩展到超过 1 种颜色;)

Sub BlackAndWhite()

  On Error Resume Next
  Kill Environ$("temp") & "\DropMe.mdb"
  On Error GoTo 0

  Dim cat
  Set cat = CreateObject("ADOX.Catalog")
  With cat
    .Create _
        "Provider=Microsoft.Jet.OLEDB.4.0;" & _
        "Data Source=" & _
        Environ$("temp") & "\DropMe.mdb"
    With .ActiveConnection

      Dim Sql As String

      Sql = _
          "CREATE TABLE Table1" & vbCr & "(" & vbCr & " Color VARCHAR(100)" & _
          " NOT NULL, " & vbCr & " Room_type NVARCHAR(100) NOT" & _
          " NULL, " & vbCr & " UNIQUE (Color, Room_type)" & vbCr & ");"
      .Execute Sql
      Sql = _
          "CREATE VIEW Table1ColorTallies" & vbCr & "(" & vbCr & " Color," & _
          " tally" & vbCr & ")" & vbCr & "AS " & vbCr & "SELECT Color, COUNT(*) AS tally" & vbCr & "" & _
          "  FROM Table1" & vbCr & " GROUP " & vbCr & "    BY Color;"
      .Execute Sql
      Sql = _
          "CREATE VIEW Table1ColorsWithMaxTallies" & vbCr & "(" & vbCr & "" & _
          " Color" & vbCr & ")" & vbCr & "AS " & vbCr & "SELECT T1.Color" & vbCr & "  FROM Table1ColorTallies" & _
          " AS T1" & vbCr & " WHERE T1.tally = (" & vbCr & "            " & _
          "       SELECT MAX(T2.tally)" & vbCr & "           " & _
          "          FROM Table1ColorTallies AS T2" & vbCr & "" & _
          "                  );"
      .Execute Sql
      Sql = _
          "INSERT INTO Table1 (Color, Room_type) VALUES" & _
          " ('Black', 'Large');"
          .Execute Sql
      Sql = _
          "INSERT INTO Table1 (Color, Room_type) VALUES" & _
          " ('White', 'Large');"
          .Execute Sql
      Sql = _
          "INSERT INTO Table1 (Color, Room_type) VALUES" & _
          " ('White', 'Small');"
          .Execute Sql
      Sql = _
          "INSERT INTO Table1 (Color, Room_type) VALUES" & _
          " ('White', 'Med');"
          .Execute Sql
      Sql = _
          "INSERT INTO Table1 (Color, Room_type) VALUES" & _
          " ('Black', 'Small');"
          .Execute Sql

      Sql = _
          "SELECT Color" & vbCr & "  FROM Table1ColorsWithMaxTallies" & vbCr & "" & _
          " WHERE 1 = (" & vbCr & "            SELECT COUNT(*)" & vbCr & "" & _
          "              FROM Table1ColorsWithMaxTallies" & _
          " AS T2" & vbCr & "           );"

      Dim rs
      Set rs = .Execute(Sql)
      MsgBox rs.GetString

    End With
    Set .ActiveConnection = Nothing
  End With
End Sub

您可以尝试以下实现:

SELECT Table1.[Room Type], 
        Count(IIf(Table1.Color="White",1,Null)) AS CountWhite, 
        Count(IIf(Table1.Color="Black",1,Null)) AS CountBlack, 
        IIf(CountWhite>CountBlack,"White",(IIf(CountBlack>CountWhite,"Black","Tie"))) AS Expr1
 FROM Table1
 GROUP BY Table1.[Room Type];

我认为类似以下内容可以完成您所描述的内容:

SELECT RoomType, 
IIF(BlackCount>WhiteCount, "Black", IIF(BlackCount<WhiteCount, "White", "Unidentified")) AS PrevailingColor

FROM
(SELECT RoomType, SUM(IIF(Color="Black",1,0)) AS BlackCount, SUM(IIF(Color="White",1,0)) AS WhiteCount 
FROM Table1
GROUP BY RoomType)
;

从 MS Access 中的以下查询开始。 在我的示例中,我使用名称 qryRoomColorCounts 保存了它:

SELECT 
tblRooms.RoomType, tblRooms.Color, Count(*) AS ColorCount 
FROM tblRooms 
GROUP BY tblRooms.RoomType, tblRooms.Color

然后,您可以使用此 SQL 来获得结果:

SELECT 
tblRooms.RoomType, 
(SELECT TOP 1 qryRoomColorCounts.Color FROM qryRoomColorCounts WHERE
 qryRoomColorCounts.RoomType=tblRooms.RoomType 
 ORDER BY qryRoomColorCounts.ColorCount DESC) AS MostUsedColor 
FROM tblRooms 
GROUP BY tblRooms.RoomType

我无法让您的建议生效,请您调试一下:不需要引用(使用后期绑定),只需粘贴到任何 VBA 标准代码模块(例如使用 Excel)并运行:

Sub NotSoBlackAndWhite()

  On Error Resume Next
  Kill Environ$("temp") & "\DropMe2.mdb"
  On Error GoTo 0

  Dim cat
  Set cat = CreateObject("ADOX.Catalog")
  With cat
    .Create _
        "Provider=Microsoft.Jet.OLEDB.4.0;" & _
        "Data Source=" & _
        Environ$("temp") & "\DropMe2.mdb"
    With .ActiveConnection

      Dim Sql As String

      Sql = _
          "CREATE TABLE tblRooms" & vbCr & "(" & vbCr & " Color VARCHAR(100)" & _
          " NOT NULL, " & vbCr & " RoomType NVARCHAR(100) NOT" & _
          " NULL, " & vbCr & " UNIQUE (Color, RoomType)" & vbCr & ");"
      .Execute Sql
      Sql = _
          "CREATE VIEW qryRoomColorCounts AS " & vbCr & "SELECT" & _
          " " & vbCr & "tblRooms.RoomType, tblRooms.Color, Count(*)" & _
          " AS ColorCount " & vbCr & "FROM tblRooms " & vbCr & "GROUP BY" & _
          " tblRooms.RoomType, tblRooms.Color"
      .Execute Sql
      Sql = _
          "INSERT INTO tblRooms (Color, RoomType) VALUES" & _
          " ('Black', 'Large');"
          .Execute Sql
      Sql = _
          "INSERT INTO tblRooms (Color, RoomType) VALUES" & _
          " ('White', 'Large');"
          .Execute Sql
      Sql = _
          "INSERT INTO tblRooms (Color, RoomType) VALUES" & _
          " ('White', 'Small');"
          .Execute Sql
      Sql = _
          "INSERT INTO tblRooms (Color, RoomType) VALUES" & _
          " ('White', 'Med');"
          .Execute Sql
      Sql = _
          "INSERT INTO tblRooms (Color, RoomType) VALUES" & _
          " ('Black', 'Small');"
          .Execute Sql

      Sql = _
          "SELECT " & vbCr & "tblRooms.RoomType, " & vbCr & "(SELECT TOP" & _
          " 1 qryRoomColorCounts.Color FROM qryRoomColorCounts" & _
          " WHERE" & vbCr & " qryRoomColorCounts.RoomType=tblRooms.RoomType" & _
          " " & vbCr & " ORDER BY qryRoomColorCounts.ColorCount" & _
          " DESC) AS MostUsedColor " & vbCr & "FROM tblRooms " & vbCr & "GROUP" & _
          " BY tblRooms.RoomType"

      Dim rs
      Set rs = .Execute(Sql)  ' <--- ERROR HERE '
      MsgBox rs.GetString

    End With
    Set .ActiveConnection = Nothing
  End With
End Sub

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM