一个 sql (oracle) 查询,用于获取每列有两个不同(空和非空)值的唯一信息

发布于 2024-11-27 11:08:36 字数 1756 浏览 3 评论 0原文

为了清楚起见,表 foobar 的结构如下:

id, action_dt, status_id
1, '02-JUL-10', 'x'
1, '02-JUL-10', '2'
1, '02-JUL-10', NULL
2, '02-JUL-10', 'a'
2, '02-JUL-10', 'b'
3, '02-JUL-10', 'k'
3, '02-JUL-10', NULL
3, '03-JUL-10', 'k'
3, '03-JUL-10', NULL

我需要一个查询来获取 ID,以便每个 ID 每天都存在一个 NULL 值和一个 NOT NULL 值。因此,在上面的示例数据集中,查询需要返回:

'02-JUL-10', 1
'02-JUL-10', 3
'03-JUL-10', 3

是的,可以使用类似以下内容来完成:

SELECT
    nulls.action_dt
    , nulls.id 

FROM        (SELECT 
                action_dt
                , id 
            FROM        foobar 
            WHERE       status_id IS NULL
            GROUP BY    action_dt)   nulls

INNER JOIN (SELECT
                action_dt
                , id
            FROM        foobar 
            WHERE       status_id IS NOT NULL
            GROUP BY    action_dt)    non_nulls     ON nulls.action_dt = non_nulls.action_dt 
                                                        AND nulls.id = non_nulls.id



但正如您所看到的,除其他外,还有两个子查询和另一个用于连接的迭代...

我的查询一直致力于并希望具有以下形式:

SELECT
    action_dt
    , id
FROM
    foobar
GROUP BY
    action_dt
    , id
    , CASE WHEN status_id IS NOT NULL THEN 1 ELSE 0 END
HAVING
    COUNT(prim_card_nb) > 1

但它并没有完全返回我需要的内容(如您所知,HAVING 子句适用于正在查询的基础数据)。有什么想法吗?

毕竟,似乎解决方案是将上述查询放在子查询中并以这种方式过滤它,例如:

SELECT
    action_dt
    , id
FROM        (SELECT
                action_dt
                , id
            FROM
                foobar
            GROUP BY
                action_dt
                , id
                , CASE WHEN status_id IS NOT NULL THEN 1 ELSE 0 END
            ) repeat_ids_per_day
GROUP BY
    action_dt
    , id
HAVING
    COUNT(id) > 1

但我觉得它可以更好......

Table foobar is, for clarity, structured and has data as follows:

id, action_dt, status_id
1, '02-JUL-10', 'x'
1, '02-JUL-10', '2'
1, '02-JUL-10', NULL
2, '02-JUL-10', 'a'
2, '02-JUL-10', 'b'
3, '02-JUL-10', 'k'
3, '02-JUL-10', NULL
3, '03-JUL-10', 'k'
3, '03-JUL-10', NULL

I need a query that gets IDs such that for each ID a NULL value and a NOT NULL value exists per day. So, in the example dataset above, the query needs to return:

'02-JUL-10', 1
'02-JUL-10', 3
'03-JUL-10', 3

Yes, it can be done using something like:

SELECT
    nulls.action_dt
    , nulls.id 

FROM        (SELECT 
                action_dt
                , id 
            FROM        foobar 
            WHERE       status_id IS NULL
            GROUP BY    action_dt)   nulls

INNER JOIN (SELECT
                action_dt
                , id
            FROM        foobar 
            WHERE       status_id IS NOT NULL
            GROUP BY    action_dt)    non_nulls     ON nulls.action_dt = non_nulls.action_dt 
                                                        AND nulls.id = non_nulls.id



but as you can see, among other things, two subqueries and another iteration for the join...

The query I've been working on and have hopes for is of the form:

SELECT
    action_dt
    , id
FROM
    foobar
GROUP BY
    action_dt
    , id
    , CASE WHEN status_id IS NOT NULL THEN 1 ELSE 0 END
HAVING
    COUNT(prim_card_nb) > 1

but it doesn't quite return what I need (as you know, the HAVING clause applies to the underlying data that is being queried). Any ideas?

After all this, it seems a solution would be to have the above query in a subquery and filter it down that way, such as:

SELECT
    action_dt
    , id
FROM        (SELECT
                action_dt
                , id
            FROM
                foobar
            GROUP BY
                action_dt
                , id
                , CASE WHEN status_id IS NOT NULL THEN 1 ELSE 0 END
            ) repeat_ids_per_day
GROUP BY
    action_dt
    , id
HAVING
    COUNT(id) > 1

but I feel it can be better...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

请恋爱 2024-12-04 11:08:36

您的想法是合理的:在这种情况下,您不需要子查询,聚合就足够了,并且应该更有效。这应该有效:

SQL> SELECT action_dt, id
  2    FROM foobar
  3   GROUP BY action_dt, ID
  4  HAVING COUNT(DISTINCT CASE WHEN status_id IS NULL THEN 1 ELSE 0 END) > 1;

ACTION_DT         ID
--------- ----------
02-JUL-10          1
02-JUL-10          3
03-JUL-10          3

Your idea is sound: in such a case you don't need a subquery, an aggregate is sufficient and should be more efficient. This should work:

SQL> SELECT action_dt, id
  2    FROM foobar
  3   GROUP BY action_dt, ID
  4  HAVING COUNT(DISTINCT CASE WHEN status_id IS NULL THEN 1 ELSE 0 END) > 1;

ACTION_DT         ID
--------- ----------
02-JUL-10          1
02-JUL-10          3
03-JUL-10          3
落叶缤纷 2024-12-04 11:08:36

我认为你必须在你的第一个发布的查询中做一些小的改变,

如下 -

SELECT
    nulls.action_dt, nulls.id 

FROM        
(SELECT 
                action_dt
                , id        
            FROM        foobar 
            WHERE       status_id IS NULL
            GROUP BY    action_dt,id
uniou all
SELECT
                action_dt
                , id
            FROM        foobar 
            WHERE       status_id IS NOT NULL
            GROUP BY    action_dt,id)  
group by action_dt, id
having count(*) >1

你发布的内容不正确,就像在oracle数据库中一样。
选择时不能包含未分组的列名称。
所以请检查一下..这可能是你的错误..也可能是问题的原因..

I think you have to do some minor changes in your first posted query

as below -

SELECT
    nulls.action_dt, nulls.id 

FROM        
(SELECT 
                action_dt
                , id        
            FROM        foobar 
            WHERE       status_id IS NULL
            GROUP BY    action_dt,id
uniou all
SELECT
                action_dt
                , id
            FROM        foobar 
            WHERE       status_id IS NOT NULL
            GROUP BY    action_dt,id)  
group by action_dt, id
having count(*) >1

what you have posted there is not a correct, as in oracle database..
you can't include not grouped column name while selecting..
so please check that .. it could be your mistake .. and may be it was couse of problem..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文