SQL - MS Access - если заявление - PullRequest
1 голос
/ 04 мая 2011

У меня есть следующая таблица:

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

Я хочу выполнить запрос:

  • Если данные показывают, что белый цвет встречается чаще, чем черный для цветов больших комнат , то результатом будет белый
  • Если данные показывают, что черный цвет встречается чаще, чем белый, то результат будет черным.
  • Если данные показывают, что у черных столько же, сколько у белых, результат будет неопознанным.

Обратите внимание, что мой запрос более сложен, чем этот, и в нем есть другие столбцы и много таблиц, но я просто хочу добавить столбец, который указывает, являются ли большие комнаты в основном белыми или черными.

Ответы [ 5 ]

3 голосов
/ 05 мая 2011

Для всех типов номеров:

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"
0 голосов
/ 06 мая 2011

Я думаю, что-то вроде следующего выполнило бы то, что вы описали:

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)
;
0 голосов
/ 04 мая 2011

Поскольку это Access (ACE, Jet, что угодно), нам, вероятно, нужно использовать промежуточные результирующие наборы через VIEW s (сохраненные объекты запросов, 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 Query Mode .В качестве альтернативы, создайте их как сохраненные объекты запроса (querydefs, что угодно), используя пользовательский интерфейс Access (DAO, что угодно) обычным способом.


Вот несколько VBA для создания новой базы данных с именем DropMe.mdb в вашемвременная папка, создайте Table1 с примерами данных, затем создайте мои предложенные VIEW s и покажите результат моего предложенного запроса в окне сообщения.Использует ADO, но никаких ссылок не требуется (используется позднее связывание).Просто вставьте в любой стандартный модуль кода VBA (например, используйте Excel) и запустите.Я думаю, что это будет хорошо масштабироваться до более чем одного цвета;)

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
0 голосов
/ 04 мая 2011

Начните со следующего запроса в 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
0 голосов
/ 04 мая 2011

Поскольку ваш вопрос еще не ясен, мы должны сделать несколько довольно широких догадок о том, что вы ищете. Если ваш стол действительно больше похож на:

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.

Теперь вам просто нужно постобработать, чтобы предоставить вам информацию, которую вы ищете - если мои догадки оправданы.


Редактировать: Необходимо использовать NVL () или эквивалентный для RoomType и включать псевдонимы таблиц; сейчас тестируется и выдает правильный ответ на MacOS X 10.6.7 с IBM Informix Dynamic Server 11.70.FC1:

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

Если MS Access не поддерживает FULL 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. Учитывая данные испытаний, он дает тот же результат. Вы можете немного его сжать, используя White.RoomType в основном списке выбора первой половины UNION (вместо выражения NVL) и Black.RoomType во второй половине.

Если MS Access не поддерживает какие-либо внешние объединения, то (а) пришло время перейти на настоящую СУБД и (б) дайте мне знать, и мы разработаем длинный трехсторонний способ выполнения UNION та же работа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...