SQLite: объединение ИЛИ и И - PullRequest
       2

SQLite: объединение ИЛИ и И

2 голосов
/ 22 августа 2010

Это постоянные вопросы от Выбор самой высокой зарплаты

Предполагая таблицу ' wagetable '

  name     lowhours  highhours  wage  priority 
  Default  0.0       40.0       100   0        
  Default  40.0      50.0       150   0        
  Default  50.0      70.5       154   0        
  Default  70.5      100.0      200   0        
  Brian    0.0       40.0       200   1        
  Brian    40.0      50.0       250   1        
  Brian    50.0      60.0       275   1        
  Brian    60.0      70.0       300   1        
  Brian    70.0      80.0       325   1        
  Brian    80.0      9999.0     350   1        
  Chad     0.0       40.0       130   1        
  Chad     40.0      9999.0     170   1  

В настоящее время я выполняю два типа запросов 3-4 раза в секунду, поэтому производительность является ключевым фактором, а не удобочитаемостью (но предпочтительнее).

Этот запрос выбирает заработную плату тогда и только тогда, когда $ Hour находится между lowhours и highhours:

SELECT wage 
FROM wagetable 
WHERE name LIKE '$Employee' OR name LIKE 'Default' 
AND '$Hour' BETWEEN lowhours AND highhours 
ORDER BY priority DESC 
LIMIT 1

Этот второй запрос запускается, если первый не смог найти $ Hour между lowhours и highhours:

SELECT wage 
FROM wagetable 
WHERE name LIKE '$Employee' OR name LIKE 'Default' 
ORDER BY priority DESC, highhours DESC
LIMIT 1

Я ищу, может ли быть запрос, в котором я мог бы объединить оба, чтобы сделать одно и то же в одном запросе

Редактировать:

Поскольку я не правильно протестировал вышеуказанные запросы ... Я скажу вам, что я хочу на английском языке и примеры ответов.

Он будет проверять, что $ Employee существует на столе, а затем использовать его. Если это не так, то вместо этого проверьте «По умолчанию». Как только он узнает имя, он проверит, находится ли $ Hour между известными низкими и старшими часами, если это произойдет, ВЫБЕРИТЕ эту заработную плату, если она выше, чем что-либо из перечисленного, автоматически получит заработную плату за самый высокий час.

Вот некоторые значения. Обратите внимание, что «Сэм» не на столе, поэтому он будет «По умолчанию» Примеры следуют этому формату: (Имя, час) ОЖИДАЕМЫЙ ОТВЕТ

(Sam, 1)        100
(Sam, 51)       154
(Sam, 999999)   200

(Brian, 1)      200
(Brian, 51)     275
(Brian, 999999) 350

Здесь снова приведена таблица, чтобы вы могли быстро получить справку, помните, что Сэм будет «По умолчанию»

name     lowhours  highhours  wage  priority 
Default  0.0       40.0       100   0        
Default  40.0      50.0       150   0        
Default  50.0      70.5       154   0        
Default  70.5      100.0      200   0        
Brian    0.0       40.0       200   1        
Brian    40.0      50.0       250   1        
Brian    50.0      60.0       275   1        
Brian    60.0      70.0       300   1        
Brian    70.0      80.0       325   1        
Brian    80.0      9999.0     350   1      

Редактировать 2:

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

Наименьшее значение lowhours будет всегда равно 0,0, пара lowhours и highhours никогда не будет иметь пробелов (Это не позволит 40-50, а затем пропустить и выполнить 60-70). То, что является неопределенным, является самым высоким highhours. Следовательно, если $Hour выше, чем самый высокий $Employee *1043*, то он должен использовать самую высокую заработную плату $Employee highhours.

Например; Если «Бетти Сью» проработала 200 часов, она получит наивысшую заработную плату Default highhours ..., которая составляет 200. Следовательно, заработная плата «Бетти Сью» на ее 200-м часу составляет 200 в час.

Теперь, если Брайан работает 10000 часов, он будет НЕ заработать Default самую высокую highhours заработную плату ... но вместо этого он получит Brian самую высокую highhours заработную плату, которая 350.

Результаты теста:

Это основано на 2000 запросах (1000 для совпадения и 1000 для несоответствия по умолчанию):

Метод Тимви: 4348 миллисекунд

Метод OMG Пони: 5843 миллисекунды

Мой метод, использующий до 5 запросов и по крайней мере 2: 5844 миллисекунды

Ответы [ 2 ]

3 голосов
/ 22 августа 2010

Я считаю, что это самый простой способ сделать то, что вы хотите:

SELECT IFNULL(
    (SELECT wage FROM WAGETABLE WHERE name LIKE '$Employee'
                 AND '$Hour' BETWEEN lowhours AND highhours),
    (SELECT wage FROM WAGETABLE WHERE name LIKE 'Default'
                 ORDER BY highhours DESC LIMIT 1)
)

Он делает то, что вы описываете в другом вопросе:

  • Получить зарплату для $ Employee;
  • Если для $ Employee нет строки, это приводит к NULL, поэтому включается ISNULL;
  • Только если первый результат был НЕДЕЙСТВИТЕЛЕН, извлекается строка по умолчанию.

ОДНАКО, Мне кажется, я должен указать, что запросы, которые вы отправили в этом вопросе, что-то другое . Мой запрос не находит строку По умолчанию , которая имеет соответствующий lowhours / highhours интервал, он возвращает только ту, которая имеет самый высокий highhours по умолчанию. Я не знаю, является ли запрос в вопросе действительно тем, что вы хотите, но он кажется более вероятным, поэтому вот запрос, который эквивалентен тому, что вы фактически задаете в этом вопросе :

SELECT IFNULL(
    (SELECT wage FROM WAGETABLE WHERE (name LIKE '$Employee' OR name='Default')
                 AND '$Hour' BETWEEN lowhours AND highhours
                 ORDER BY priority DESC LIMIT 1),
    (SELECT wage FROM WAGETABLE WHERE name LIKE '$Employee' OR name='Default'
                 ORDER BY priority DESC, highhours DESC LIMIT 1)
)
1 голос
/ 22 августа 2010

Вот что я упомянул в своем комментарии к Алексу:

SELECT s.wage
  FROM (SELECT x.wage
          FROM WAGETABLE x
         WHERE x.name LIKE '$Employee'
           AND '$Hour' BETWEEN x.lowhours AND x.highhours
        UNION ALL
        SELECT y.wage AS wage
          FROM WAGETABLE y
          JOIN (SELECT wt.name,
                       MAX(wt.highhours) AS max_hours
                  FROM WAGETABLE wt
              GROUP BY wt.name) bb ON bb.name = y.name
                                  AND bb.max_hours = y.highhours
         WHERE y.name LIKE '$Employee'
        UNION ALL
        SELECT t.wage
          FROM WAGETABLE t
         WHERE t.name = 'Default'
           AND '$Hour' BETWEEN t.lowhours AND t.highhours
        UNION ALL
        SELECT z.wage
          FROM WAGETABLE z
          JOIN (SELECT wt.name,
                       MAX(wt.highhours) AS max_hours
                  FROM WAGETABLE wt
              GROUP BY wt.name) aa ON aa.name = z.name
                                  AND aa.max_hours = z.highhours
         WHERE z.name LIKE 'Default') s
 LIMIT 1

Ранее:

SELECT s.wage
  FROM (SELECT x.wage
          FROM WAGETABLE x
         WHERE x.name LIKE '$Employee'
           AND '$Hour' BETWEEN x.lowhours AND x.highhours
        UNION ALL
        SELECT y.wage
          FROM WAGETABLE y
         WHERE y.name LIKE 'Default'
           AND y.highhours = (SELECT MAX(highhours)
                                FROM WAGETABLE wt
                               WHERE wt.name = y.name)) s
 LIMIT 1

Из-за выбора соответствия для пользователя / etc находится в верхней частиСОЮЗ, если такая запись существует - это будет первый ряд.Если совпадений нет, совпадение по умолчанию будет первой строкой.Значение по умолчанию всегда будет в наборе результатов, следовательно, необходимость в LIMIT ...

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