SQLite:组合OR和AND

时间:2010-08-22 02:42:19

标签: sql mysql sqlite

这是Selecting the highest salary

的问题

假设表格“可投资

  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,则第二个查询起飞:

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

我希望看看是否有一个查询,我可以将两者结合起来只在一个查询中做同样的事情

编辑:

因为我没有正确测试上述查询..我会用英语告诉你我想要的东西和答案的例子。

它会检查表上是否存在$ Employee,然后使用它。如果没有,那么请检查“默认”。一旦知道了名字,它就会检查$ Hour是否在已知的工作时间和工作时间之间,如果确实如此,那么选择该工资,如果它高于列出的任何工资,则自动获取最高工时的工资。

以下是一些值。请注意,“sam”不在桌面上,所以他将是'默认' 示例遵循以下格式: (姓名,小时)预期答案

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

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

这是表格,所以你可以快速参考,记住Sam将是'默认'

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将-allways-为0.0,lowhourshighhours对将不会有任何差距(它将不允许40-50然后跳过做60-70)。不确定的是最高highhours。因此,$Hour高于$Employee的最高highhours,那么它应该使用$Employee的最高highhours工资。

例如;如果“Betty Sue”工作200小时,它将获得Default最高highhours工资......即200.因此,“Betty Sue”在第200小时的工资是每小时200。

如果布莱恩工作10000小时,他将获得Default最高highhours工资...但相反,他将获得Brian的工资最高highhours工资,即350。

基准测试的结果:

这是基于2000个查询(匹配为1000,默认不匹配为1000):

Timwi的方法:4348毫秒

OMG Ponie的方法:5843毫秒

我的方法最多使用5个查询,至少2:5844毫秒

2 个答案:

答案 0 :(得分:3)

我相信这是做你想做的最直接的方式:

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会启动;
  • 仅当第一个结果为NULL时,才会检索默认行。

但是,我觉得我应该指出您在问题中发布的查询不同的。我的查询找不到具有匹配 lowhours / highhours 间隔的默认行,它只返回具有最高的那一行highhours 表示默认值。我不知道问题中的查询是否真的是你想要的,但似乎更有可能,因此这里的查询等同于你在这个问题中实际提出的问题:< / p>

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 :(得分:1)

以下是我在对Alex的评论中提到的内容:

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

由于在UNION的上半部分选择了用户匹配,如果存在这样的记录 - 它将是第一行。如果没有匹配项,则默认匹配将是第一行。默认值始终位于结果集中,因此需要LIMIT ...