2

我之前的问题和解决方法:

从字段中获取最大值和最小值

这工作正常,但我想在这个例子中跳过 0 和 NULL。

例如:

First:
id | title 
1  | aaa
2  | bbb
3  | ccc

Second:
id | first_id | one | two    | three | four
1  |    1     | 3   | 0      | 4     | 6
2  |    2     | 4   | 4      | 1     | 2
3  |    3     | 1   | NULL   | 3     | 4

这应该告诉我:

id | title | min | max 
1  | aaa   |  3  | 6
2  | bbb   |  1  | 4
3  | ccc   |  1  | 4

不是

id | title | min | max 
1  | aaa   |  0  | 6
2  | bbb   |  1  | 4
3  | ccc   |  0  | 4

在我上一个问题的哪个示例中,实现跳过 0 和 NULL 的最佳方法是?

4

5 回答 5

1

将这些添加到您的子句中

SELECT 
    f.id, 
    f.title
    MIN(LEAST(greatest(coalesce(s.one,0),1), greatest(coalesce(s.two,0),1), greatest(coalesce(s.three,0),1), greatest(coalesce(s.four,0),1))) as min,
    MAX(GREATEST(greatest(coalesce(s.one,0),1), greatest(coalesce(s.two,0),1), greatest(coalesce(s.three,0),1), greatest(coalesce(s.four,0),1))) as max
FROM 
    First f
        INNER JOIN Second s
        on f.id = s.first_id
GROUP BY 
    f.id, 
    f.title

您可以使用coalesce(fieldName, 1)将 null 变为 1。

同样,正如您在上一个问题中所说,这是使用查询来强制回答的可怕做法。您应该更改数据库的布局。

编辑:我已经整理出了你想要的数据,但在你看之前,请注意,如果我的一位同事写了这样的脚本,他会当场被解雇。这是可怕的,不应该使用。

select
    f.id,
    f.title,
    (select min(z.myVal) from
        (
select
    b.id,
    b.first_id,
    b.one as myVal
from
    second b
where
    b.one is not null
    and b.one > 0
union
select
    b.id,
    b.first_id,
    b.two as myVal
from
    second b
where
    b.two is not null
    and b.two > 0
union
select
    b.id,
    b.first_id,
    b.three as myVal
from
    second b
where
    b.three is not null
    and b.three > 0
union
select
    b.id,
    b.first_id,
    b.four as myVal
from
    second b
where
    b.four is not null
    and b.four > 0
        ) z
    where
    f.id=z.first_id) as miniVal,
    greatest(
        coalesce(s.one,0),
        coalesce(s.two,0),
        coalesce(s.three,0),
        coalesce(s.four,0)  
    ) as maxiVal
from
    first f,
    second s
where
    f.id=s.first_id

输出数据

+------+-------+---------+---------+
| id   | title | miniVal | maxiVal |
+------+-------+---------+---------+
|    1 | aaaa  |       3 |       6 |
|    2 | bbbb  |       1 |       4 |
|    3 | cccc  |       1 |       4 |
+------+-------+---------+---------+
3 rows in set (0.00 sec)

运行这个查询让我有点呕吐。像这样写SQL是多么的错误。

于 2012-07-09T09:53:47.683 回答
1

虽然看起来很笨重,但这个解决方案应该可以工作:

SELECT 
    a.id, a.title, MIN(b.num) AS min, MAX(b.num) AS max
FROM 
    first a
LEFT JOIN
(
    SELECT first_id, one AS num FROM second UNION ALL
    SELECT first_id, two FROM second UNION ALL
    SELECT first_id, three FROM second UNION ALL
    SELECT first_id, four FROM second 
) b ON 
    a.id = b.first_id AND 
    b.num IS NOT NULL AND 
    b.num > 0
GROUP BY 
    a.id, a.title

这样做是它实际上将每个数字列放入自己的行中,但只有不为空且 > 0 的数字。在 之前GROUP BY,结果LEFT JOIN将如下所示:

id  |  title  |  num
---------------------
1   |  aaa    |  3
1   |  aaa    |  4
1   |  aaa    |  6
2   |  bbb    |  1
2   |  bbb    |  2
2   |  bbb    |  4
2   |  bbb    |  4
3   |  ccc    |  1
3   |  ccc    |  3
3   |  ccc    |  4

first然后通过每个( )的分组GROUP BY a.id, a.title,我们可以使用列上的MIN()MAX()聚合函数来提取每个组的num最小值和最大值:first

id  |  title  |  min  |  max
----------------------------
1   |  aaa    |  3    |  6
2   |  bbb    |  1    |  4
3   |  ccc    |  1    |  4

如果 a 的first_id所有四列都具有NULL's 或's,则由于使用 a而不是a 而0显示最小值和最大值,因为我相信这对于您的情况来说是更好的行为:NULLLEFT JOININNER JOIN

id  |  title  |  min  |  max
----------------------------
4   |  ddd    |  NULL |  NULL
于 2012-07-09T10:10:17.610 回答
0

我认为您只需要嵌套 LEAST 表达式:

LEAST(
    NULLIF(one,0),
    LEAST(
        NULLIF(two,0),
            LEAST(
                NULLIF(three,0),
                LEAST(
                    NULLIF(four,0),
                    null ))))

编辑我刚刚查了一下。LEAST 函数接受多个参数:

LEAST( NULLIF(one,0), NULLIF(two,0), NULLIF(three,0), NULLIF(four,0))

编辑 2我看到你想要最小值和最大值。显然,您只需根据需要将 LEAST 更改为 GREATEST 或将 MIN 更改为 MAX。

这可能更直接,或者您可能没有方便的最少功能。

SELECT
    f.id, f.title,
    (
        SELECT MIN(NULLIF(val, 0))
        FROM
            (
                SELECT one AS val UNION ALL
                SELECT two UNION ALL
                SELECT three UNION ALL
                SELECT four
            ) AS vals
        ) 
    ) as minval

FROM First f INNER JOIN Second s on f.id = s.first_id

您尚未指定是否所有四列都可能为 null/0。我们可能需要针对这种情况进行调整。

于 2012-07-09T16:33:29.057 回答
0

利用:

WHERE COLUMN IS NOT NULL AND COLUMN <> 0;
于 2012-07-09T10:00:04.077 回答
0

您可以使用IFNULL()

WHERE IFNULL(fieldname, 0) != 0
于 2012-07-09T10:26:33.403 回答