这三个查询有什么区别?在哪里& HAVING - mysql版本?

时间:2016-01-16 23:46:34

标签: mysql

我在这里有3个查询有什么区别?

第一个版本适用于我的localhost xampp mysql数据库(10.1.9-MariaDB)。但是,它使用我的在线测试服务器mysql数据库(5.7.9-log MySQL社区服务器GPL)检索0结果。

第二个版本检索两个服务器的预期结果。但是在我的localhost查询2中检索相同的结果集,虽然顺序不同,但是我猜这是因为我没有订单。

这是不同版本的mysql的问题吗?如何,如果我的查询不同?

查询1

TC_char_profiles

QUERY2

SELECT 
    s.eid, e.fname, e.lname, s.id, s.starttime, s.finishtime
FROM
    employees AS e
        RIGHT JOIN
    scheduling_shifts AS s USING (eid)
GROUP BY s.id
HAVING COUNT(s.date = '2016-01-15' OR NULL) > 0
    AND COUNT(s.eid = '1' OR NULL) = 0;

EDIT :: 的 QUERY3

此查询还检索正确的结果集减去NULL SELECT s.eid, e.fname, e.lname, s.id, s.starttime, s.finishtime FROM employees AS e RIGHT JOIN scheduling_shifts AS s USING (eid) WHERE s.date = '2016-01-15' GROUP BY s.id HAVING COUNT(s.eid = '1' OR NULL) = 0;

s.eid

编辑::以下是我自己在SQLfiddle

上查询的测试用例

目标是在所选日期获取所选员工的可能互换列表。我们选择的日期是 SELECT s.eid, e.fname, e.lname, s.id, s.starttime, s.finishtime FROM employees AS e RIGHT JOIN scheduling_shifts AS s USING (eid) WHERE s.date = '2016-01-15' AND s.eid <> '1' ,我们想要换班的选定员工是员工15th Jan 2016。该列表无法取得自己的转变,因为他无法与自己交换班次。但它应该带来未分配的转变。 (1eid)的位移。因此,该选项会显示其他员工及其轮班的列表,或者在这一天我们可以与我们交换的未分配班次。

请注意查询1 - 确实会在此生成正确的结果,执行会在xampp(mariadb 10)上生成正确的结果,但没有在我的在线测试服务器上。

查询2 也会获取正确的结果,同时也会执行xampp和在线测试服务器。

查询3 会抓取所有已分配的班次,但不会取消未分配的班次。

希望这能更好地解释我的问题。

1 个答案:

答案 0 :(得分:2)

WHERE子句考虑每行的条件,HAVING子句考虑聚合,但我不认为这是差异的原因。

你使用&#34; OR NULL&#34;是误导性的,并且会在某些时候(如果不是现在)产生意外或不正确的结果,请注意,当表达式为NON-NULL 时, COUNT()递增。 / p>

下面,使用MySQL 5.6 at SQL Fiddle,我尝试显示效果:

CREATE TABLE Table1
    (`ID` int, `Other` varchar(4))
;

INSERT INTO Table1
    (`ID`, `Other`)
VALUES
    (1, 'ABC'),
    (2, 'DEF'),
    (3, NULL)
;

查询1

SELECT COUNT(`other` > '0' OR NULL)
FROM Table1

<强> Results

| COUNT(OTHER > '0' OR NULL) |
|----------------------------|
|                          2 |

查询2

SELECT COUNT(`other` > '0' OR `other` IS NULL)
FROM Table1

<强> Results

| COUNT(`other` > '0' OR `other` IS NULL) |
|-----------------------------------------|
|                                       3 |

在上面的Query1中,您可以看到&#34; OR NULL&#34;不计算但在我的Query2中,表达式对所有行都返回true,因此所有行都被计算在内。

&#34; OR NULL&#34;是一个常量NULL,并且COUNT()不会为NULL增加

[编辑] 我建议您使用COUNT(*),因为看起来您想要做的就是计算每一行,这正是COUNT(*)无法访问每一列的所有内容,它所关心的只是&#39 ;行是否存在&#39;。

顺便提一下[编辑2] ......

通过&lt;&gt;比较NULL (不相等)不起作用。 NULL不能等于任何东西,因此也不可能知道它是否相等(因为你必须知道它是is equal 之前is not equal

在y&amp;列中查看关节z在以下结果中:

   SELECT
          COUNT(OTHER > '0' OR NULL) orig
        , COUNT(`other` > '0' OR `other` IS NULL) x
        , count(case when `other` <> 'abc' then NULL else 1 end) y
        , count(case when `other` <> 'abc' or `other` is null then NULL else 1 end) z
    FROM Table1

<强> Results

| orig | x | y | z |
|------|---|---|---|
|    2 | 3 | 2 | 1 |

作为一个sqlfiddle测试用例,我将如何构建查询。它列出了提供的表scheduling_shifts中的9行中的8行:

SELECT 
        s.eid, e.fname, e.lname, s.id, s.date, s.starttime, s.finishtime
FROM scheduling_shifts s
      LEFT JOIN employees AS e on s.eid = e.eid
WHERE (s.eid <> 1 OR s.eid is null)
      AND s.date = '2016-01-15';

由于我无法重现您的具体问题(来自不同平台的不同结果),我遗憾地说只有您使用&#34;或NULL&#34;让我感到不寻常,并可能产生不可预测的结果。作为查询的第二个特性,当你没有特别的理由时,你正在使用having子句,我也会避免这样做。