2016-12-15 39 views
2

我希望找到GROUPID的情况下,所有的价格值为0以下是我所期待的如何使用自联接在组内找到相同的值?

-------------------------------- 
| Groupid | Price | Customer| 
-------------------------------- 
| 001  | 9  | 4  | 
| 001  | 0  | 4  | 
| 002  | 4  | 4  | 
| 002  | 4  | 4  | 
| 003  | 0  | 4  | 
| 003  | 0  | 4  | 
| 004  | 4  | 4  | 
| 004  | 7  | 4  | 
-------------------------------- 

我尝试使用下面的查询查找所有GROUPID其中两个的简化版本对于特定组价格值= 0

SELECT * FROM MYTABLE WHERE GROUPID IN 
(SELECT TB1.GROUPID FROM MYTABLE TB1 JOIN MYTABLE TB2 ON TB1.GROUPID = TB2.GROUPID 
AND TB1.PRICE = 0 AND TB2.PRICE = 0) 
and CUSTOMER = 4 
ORDER BY GROUPID; 

该查询将返回:

| Groupid | Price | Customer| 
-------------------------------- 
| 001  | 9  | 4  | 
| 001  | 0  | 4  | 
| 003  | 0  | 4  | 
| 003  | 0  | 4  | 
-------------------------------- 

对我来说,我只需要我t返回GROUPID 003.

我还想要求帮助修改查询以返回groupid中的所有非0等于PRICE值。它不必与上面相同的查询。例如,退货将是:

| Groupid | Price | Customer| 
-------------------------------- 
| 002  | 4  | 4  | 
| 002  | 4  | 4  | 

任何帮助,将不胜感激。感谢您的时间。

+0

可以了'price'为空? – mathguy

+0

对于这类问题,连接很少是正确的答案。 GROUP BY和HAVING子句是更有效的方法(Gordon根据这些方法发布了答案)。 – mathguy

回答

3

如果所有的价格都为零,再看看最低和最高价格为GROUPID:

select groupid 
from mytable t 
group by groupid 
having min(price) = 0 and max(price) = 0; 

我应该指出的是,没有自联接需要这个。

+0

一如既往的出色答案。请提问。在一张大桌子上哪一个会更快?聚合或自我加入或相关查询? – GurV

+0

@GurwinderSingh - 在任何大小的表上,聚合将比联接快。在许多情况下,相关子查询的速度甚至比连接速度慢(尽管优化器也知道这一点,所以在简单情况下 - 就像这样 - 它会将相关的子查询转换为连接)。 – mathguy

+0

@mathguy谢谢。我应该指出,这个答案的结果只给出了groupid,但OP要求所有的列。因此,* IN *子句或相关的查询仍然需要。 – GurV

0

试试这个:

SELECT * FROM MYTABLE as m1 where Price = 0 
and not exists (
    select 1 
    from MYTABLE as m2 
    where m2.Groupid = m1.Groupid 
    and m2.Price <> 0 
    ) 
0

您可以列出行,其GROUP_ID有非零价格没有行

select groupid, price, customer from mytable t 
where not exists (
    select 1 from mytable where group_id = t.group_id 
    and price != 0 
); 
0

编辑 戈登的是第一个最佳的解决方案部分:

SELECT groupid 
FROM mytable t 
GROUP BY GroupID 
HAVING (MAX(price) = 0 and MIN(price) = 0) 

而且对于第二部分:

SELECT groupid 
FROM mytable t 
GROUP BY GroupID 
HAVING MIN(price) <> 0 AND (MAX(price) = MIN(price)) 

我原来的一个:

SELECT groupid 
FROM mytable t 
GROUP BY GroupID 
HAVING SUM(Price) =0 

这是假设,有没有负面的价格。

你的问题的第二部分:

SELECT groupid 
FROM mytable t 
WHERE Price > 0 
GROUP BY GroupID, Price 
HAVING COUNT(price) > 1 
-1

我会做非常相似什么戈登发布

SELECT groupId 
FROM MyTable 
GROUP BY groupId 
HAVING SUM(price) = 0 
0

我将通过在各组计数不同价格的数量做(并且我假设每个组都会有同一个客户),然后根据您感兴趣的价格进行过滤。

例如,对于价格,对于每个组识别+客户的所有行都是0:

WITH mytable AS (SELECT '001' groupid, 9 price, 4 customer FROM dual UNION ALL 
       SELECT '001' groupid, 0 price, 4 customer FROM dual UNION ALL 
       SELECT '002' groupid, 4 price, 4 customer FROM dual UNION ALL 
       SELECT '002' groupid, 4 price, 4 customer FROM dual UNION ALL 
       SELECT '003' groupid, 0 price, 4 customer FROM dual UNION ALL 
       SELECT '003' groupid, 0 price, 4 customer FROM dual UNION ALL 
       SELECT '004' groupid, 4 price, 4 customer FROM dual UNION ALL 
       SELECT '004' groupid, 7 price, 4 customer FROM dual) 
SELECT groupid, 
     customer, 
     price 
FROM (SELECT groupid, 
       customer, 
       price, 
       COUNT(DISTINCT price) OVER (PARTITION BY groupid, customer) num_distinct_prices 
     FROM mytable) 
WHERE num_distinct_prices = 1 
AND price = 0; 

GROUPID CUSTOMER  PRICE 
------- ---------- ---------- 
003    4   0 
003    4   0 

只要改变and price = 0and price != 0,如果你想它们具有相同的非零价格的所有行组。或者完全删除该谓词。

0

在您的示例数据中,您只有一个客户。我假设您有多个客户,您仍然希望返回所有行和所有客户中groupid具有相同价格的行。如果是这样,你可以使用下面的查询。它与Boneist几乎相同 - 我只用min(price)和max(price)而不是count(distinct),并且我不包括customerpartition by中。

如果价格可能为空,则在计算最高价格和最低价格时将被忽略;如果所有非空价格对于一个groupid都是相等的,则该组的所有行将被返回。如果价格可能为空,并且这不是期望的行为,那么可以很容易地改变 - 但是OP必须澄清。

下面的查询检索所有的情况,当有一个单一的价格为groupid。要仅检索价格为0的组(其他条件),请将and price = 0添加到外部查询的WHERE子句中。我添加了更多测试数据来说明查询涵盖的一些情况。

with 
    test_data (groupid, price, customer) as (
     select '001', 9, 4 from dual union all 
     select '001', 0, 4 from dual union all 
     select '002', 4, 4 from dual union all 
     select '002', 4, 4 from dual union all  
     select '003', 0, 4 from dual union all 
     select '003', 0, 4 from dual union all 
     select '004', 4, 4 from dual union all  
     select '004', 7, 4 from dual union all 
     select '002', 4, 8 from dual union all 
     select '005', 2, 8 from dual union all 
     select '005', null, 8 from dual 
    ), 
    prep (groupid, price, customer, min_price, max_price) as (
     select groupid, price, customer, 
       min(price) over (partition by groupid), 
       max(price) over (partition by groupid) 
     from test_data 
    ) 
select groupid, price, customer 
from prep 
where min_price = max_price 
; 


GROUPID  PRICE CUSTOMER 
------- --------- --------- 
002    4   8 
002    4   4 
002    4   4 
003    0   4 
003    0   4 
005      8 
005    2   8 
0

这可能是你想要什么:

SELECT * FROM MYTABLE 
WHERE GROUPID NOT IN (
     SELECT GROUPID 
     FROM MYTABLE 
     WHERE Price <> 0) 

,只是更改其他查询的最后一行:

SELECT * FROM MYTABLE 
WHERE GROUPID NOT IN (
     SELECT GROUPID 
     FROM MYTABLE 
     WHERE Price = 0) 
相关问题