Присоединиться к нескольким логическим значениям - PullRequest
0 голосов
/ 18 июля 2009

У меня есть две таблицы, каждая с тремя логическими столбцами (ms-access "Yes / No").

Таблица 1: A1, B1, C1

Таблица 2: А2, В2, С2

Я бы хотел, чтобы строки из Таблицы 2 были заданы конкретной строкой из Таблицы 1, которая удовлетворяла бы следующим условиям:

Если A1 - истина, то только строки, где A2 - истина, если A1 - ложь, то строки, где A2 - истина или ложь. Если B1 - истина, то только строки, где B2 - истина, если B1 - ложь, то строки, где B2 - истина или ложь. Если C1 - это истина, то только строки, в которых C2 - это истина, если C1 - ложь, то строки, где C2 - это истина или ложь.

Пример первый

         A, B, C    
Table 1: 0, 1, 0  (selected row)

Table 2: 1, 0, 0
         0, 1, 0  (in return set)
         1, 1, 0  (in return set)
         0, 0, 1
         1, 0, 1
         0, 1, 1  (in return set)
         1, 1, 1  (in return set)

Пример два

         A, B, C    
Table 1: 0, 0, 1  (selected row)

Table 2: 1, 0, 0
         0, 1, 0  
         1, 1, 0 
         0, 0, 1  (in return set)
         1, 0, 1  (in return set)
         0, 1, 1  (in return set)
         1, 1, 1  (in return set)

Как мне лучше всего это сделать?

Например, это не работает:

SELECT        vw_fbScheduleFull.LocationName
            , vw_fbScheduleFull.FieldName
            , vw_fbScheduleFull.Description
            , vw_fbScheduleFull.StartTime
            , vw_fbScheduleFull.EndTime
            , vw_fbScheduleFull.LowerDivision
            , vw_fbScheduleFull.UpperDivision
            , vw_fbScheduleFull.SeniorDivision
FROM (vw_fbSchedule
      Full INNER JOIN fbDivision
         ON vw_fbScheduleFull.LowerDivision = fbDivision.LowerDivision
         AND fbDivision.LowerDivision = 1
         OR vw_fbScheduleFull.UpperDivision = fbDivision.UpperDivision
         AND fbDivision.UpperDivision = 1
         OR vw_fbScheduleFull.SeniorDivision = fbDivision.SeniorDivision   
         AND fbDivision.SeniorDivision = 1)
WHERE (vw_fbScheduleFull.PracticeDate = ?)
    AND (vw_fbScheduleFull.Locked IS NULL)
    AND (fbDivision.DivisionName = ?)
ORDER BY vw_fbScheduleFull.LocationName
       , vw_fbScheduleFull.FieldName
       , vw_fbScheduleFull.StartTime

Ответы [ 2 ]

3 голосов
/ 18 июля 2009

На самом деле вы задаете не проблему SQL, а проблему логического выражения. Я предполагаю, что у вас есть еще один столбец в этих таблицах, который позволяет вам соединять строки от t1 до t2, но, следуя вашим примерам (где в t1 только 1 строка), вы можете сделать это следующим образом:

  SELECT t2.A2
       , t2.B2
       , t3.C2
    FROM t1
       , t2
   WHERE (t2.A2 OR NOT T1.A1)
     AND (t2.B2 OR NOT T1.B1)
     AND (t2.C2 OR NOT T1.C1)
;

Теперь я вижу неабстрагированный ответ, который вы опубликовали выше. Исходя из этого, в вашем SQL есть некоторые проблемы. Во-первых, вы должны выражать только те условия в ваших предложениях JOIN, которые связывают таблицу vw_fbScheduleFull с таблицей fbDivision (т.е. отношение внешнего / первичного ключа); все содержимое LowerDivision / UpperDivision / SeniorDivision должно быть в предложении WHERE.

Во-вторых, вы игнорируете приоритет операторов И и ИЛИ - вы хотите заключить каждую из пар * деления в скобки, чтобы избежать нежелательных эффектов.

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

  SELECT vw_fbScheduleFull.LocationName
       , vw_fbScheduleFull.FieldName
       , vw_fbScheduleFull.Description
       , vw_fbScheduleFull.StartTime
       , vw_fbScheduleFull.EndTime
       , vw_fbScheduleFull.LowerDivision
       , vw_fbScheduleFull.UpperDivision
       , vw_fbScheduleFull.SeniorDivision
    FROM vw_fbScheduleFull 
       , fbDivision
   WHERE vw_fbScheduleFull.PracticeDate = ?
     AND vw_fbScheduleFull.Locked IS NULL 
     AND fbDivision.DivisionName = ?
     AND (vw_fbScheduleFull.LowerDivision = 1 OR fbDivision.LowerDivision <> 1)
     AND (vw_fbScheduleFull.UpperDivision = 1 OR fbDivision.UpperDivision <> 1)
     AND (vw_fbScheduleFull.SeniorDivision = 1 OR fbDivision.SeniorDivision <> 1)
ORDER BY vw_fbScheduleFull.LocationName
       , vw_fbScheduleFull.FieldName
       , vw_fbScheduleFull.StartTime 
;

Глядя еще раз, я понимаю, что ваше "fbDivision.DivisionName =?" вероятно, сокращает количество строк в этой таблице до одной, и между этими двумя таблицами нет формального отношения PK / FK. В этом случае вы должны отказаться от номенклатуры INNER JOIN в предложении FROM и просто перечислить две таблицы; Я обновил свой пример.

0 голосов
/ 18 июля 2009

Ответ Стива Броберга правильный и хороший; Я бы просто добавил, что псевдонимы могут сделать запросы намного проще для глаз:

SELECT f.LocationName
       , f.FieldName
       , f.Description
       , f.StartTime
       , f.EndTime
       , f.LowerDivision
       , f.UpperDivision
       , f.SeniorDivision
    FROM vw_fbScheduleFull f
       , fbDivision        d
   WHERE f.PracticeDate = ?
     AND f.Locked IS NULL 
     AND d.DivisionName = ?
     AND (f.LowerDivision = 1 OR d.LowerDivision <> 1)
     AND (f.UpperDivision = 1 OR d.UpperDivision <> 1)
     AND (f.SeniorDivision = 1 OR d.SeniorDivision <> 1)
ORDER BY f.LocationName
       , f.FieldName
       , f.StartTime 
;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...