2013-08-23 38 views
1

我遇到了一个问题,我正在使用Oracle SQL进行类似这样的工作。Oracle SQL - 比较行

PurchaseID CustID  Location 
----1------------1-----------A 
----2------------1-----------A  
----3------------2-----------A 
----4------------2-----------B 
----5------------2-----------A 
----6------------3-----------B 
----7------------3-----------B 

我感兴趣的查询表,返回在同一顾客在不同地点购买的所有实例。因此,对于上面的表,我会想:

输出

PurchaseID CustID  Location 
----3------------2-----------A 
----4------------2-----------B 
----5------------2-----------A 

如何做到这一点任何想法?我一直没有想到如何去做,而且我的大部分想法看起来都很笨拙。我使用的数据库有1MM +记录,所以我不希望它运行得太慢。

任何帮助,将不胜感激。谢谢!

+0

有多少个不同的位置,有多少个不同的客户? –

+0

这个问题是我在工作中真正做的一个简化版本,但是在真实数据库中,我在这里调用Location的变量有5个不同的值(也有一些为空),并且有大约500,000个不同的“客户“。 – user1895076

+0

然后,在性能方面可能是最好的构造所有五组不同位置并相交。 –

回答

8
SELECT * 
FROM YourTable T 
WHERE CustId IN (SELECT CustId 
       FROM YourTable 
       GROUP BY CustId 
       HAVING MIN(Location) <> MAX(Location)) 
+0

太快了!谢谢! Min(Location)<> MAX(Location)是否正在使其工作? – user1895076

+0

@ user1895076这是为了确保它至少有2个不同的位置。你也可以使用'HAVING COUNT(DISTINCT Location)> 1' – Lamak

+0

啊,陷阱。 Min是CustID的最少位置数量?另外,我接下来要解决这个问题,也许你可以帮忙。 我有一个购买日期的第四列。下一步是我想将上面的OUTPUT表缩小到仅在两年内在不同地点进行采购的情况。它应该返回一个客户在两年内在不同地点至少进行两次采购的所有情况。 – user1895076

0

下面是一个使用子查询

SELECT T1.PurchaseID 
     ,T1.CustID 
     ,T1.Location 
FROM YourTable T1 
INNER JOIN 
     (SELECT T2.CustID 
       ,COUNT (DISTINCT T2.Location) 
     FROM YourTable T1 
     GROUP BY 
       T2.CustID 
     HAVING COUNT (DISTINCT T2.Location)>1 
     ) SQ 
ON  SQ.CustID = T1.CustID 
7

一个方法,你应该能够使用类似以下内容:

select purchaseid, custid, location 
from yourtable 
where custid in (select custid 
        from yourtable 
        group by custid 
        having count(distinct location) >1); 

SQL Fiddle with Demo

WHERE子句中的子查询返回了具有大于1

5

在英语中不同位置的总数所有custids

如果另一行与存在选择一行同一客户和不同的地点。

在SQL:

SELECT * 
FROM atable t 
WHERE EXISTS (
    SELECT * 
    FROM atable 
    WHERE CustID = t.CustID 
    AND Location <> t.Location 
); 
+0

+1我喜欢这个比我好 – Lamak

0

这应该只需要一个全表扫描。

create table test (PurchaseID number, CustID number, Location varchar2(1)); 
insert into test values (1,1,'A'); 
insert into test values (2,1,'A'); 
insert into test values (3,2,'A'); 
insert into test values (4,2,'B'); 
insert into test values (5,2,'A'); 
insert into test values (6,3,'B'); 
insert into test values (7,3,'A'); 

with repeatCustDiffLocations as (
    select PurchaseID, custid, location, dense_rank() over (partition by custid order by location) r 
    from test) 
select b.* 
from repeatCustDiffLocations a, repeatCustDiffLocations b 
where a.r > 1 
and a.custid = b.custid; 
0

这使得最有意义的我,因为我试图在整个表返回具有相同值的行,专门为两列按照这种格式显示in this stackoverflow answer here.

回答你的问题是:

SELECT DISTINCT a.* 
FROM TEST a 
INNER JOIN TEST b 
ON a.CUSTOMERID = b.CUSTOMERID AND 
a.LOCATION <> b.LOCATION; 

然而,解决问题的办法,如矿用在多行两列具有匹配的值(在该实例2中,将产生任何结果,因为所有PurchaseID的是唯一的):

SELECT DISTINCT a.* 
FROM TEST a 
INNER JOIN TEST b 
ON a.CUSTOMERID = b.CUSTOMERID AND 
a.PURCHASEID = b.PURCHASEID AND 
a.LOCATION <> b.LOCATION; 

虽然,这不会返回基于需要查询什么正确的结果,它表明该查询逻辑工作

SELECT DISTINCT a.* 
FROM TEST a 
INNER JOIN TEST b 
ON a.CUSTOMERID = b.CUSTOMERID AND 
a.PURCHASEID <> b.PURCHASEID AND 
a.LOCATION = b.LOCATION; 

如果有人想在甲骨文尝试这里是表和值要插入:

CREATE TABLE TEST (
PurchaseID integer, 
CustomerID integer, 
Location varchar(1)); 

INSERT ALL 
    INTO TEST VALUES (1, 1, 'A') 
    INTO TEST VALUES (2, 1, 'A') 
    INTO TEST VALUES (3, 2, 'A') 
    INTO TEST VALUES (4, 2, 'B') 
    INTO TEST VALUES (5, 2, 'A') 
    INTO TEST VALUES (6, 3, 'B') 
    INTO TEST VALUES (7, 3, 'B') 
SELECT * FROM DUAL;