Reputation: 435
(reverting edit) I have a table that houses keys and values of configuration for different customer.
CustomerID Key Value
C1 AskPhoneNo TRUE
C1 Website C1Website.com
C1 Report TRUE
C2 AskPhoneNo TRUE
C2 Report FALSE
C2 AskAddress TRUE
I need to compare the data between C1 and C2 and Show diffs like this
C1 AskPhoneNo TRUE C2 AskPhoneNo TRUE
C1 Website C1Website.com C2 - -
C1 Report TRUE C2 Report False
C1 AskAddress - C2 AskAddress
What query can be used to get this result?
Upvotes: 0
Views: 797
Reputation: 95072
In order to compare all customers with each other, first join customer to customer. Cross join all keys. Then outer join the data:
with customers as (select distinct customerid from mytable)
select
k.key,
c1.customerid as customerid1, m1.value as value1,
c2.customerid as customerid2, m2.value as value2
from customers c1
join customers c2 on c2.customerid > c1.customerid
cross join (select distinct key from mytable) k
left join mytable m1 on m1.customerid = c1.customerid and m1.key = k.key
left join mytable m2 on m2.customerid = c2.customerid and m2.key = k.key
order by customerid1, customerid2, k.key;
(I suppose you have a customers table, so you can remove the WITH
clause.)
Upvotes: 0
Reputation: 3465
Here is a version with parameterized Customer IDs
with
Cust1 as (select 'C1' as C_id from DUAL)
,Cust2 as (select 'C2' as C_id from DUAL)
select (select C_id from Cust1) ID1,
coalesce(t1.K, t2.K) Key1,
t1.V as Value1,
(select C_id from Cust2) ID2,
coalesce(t2.K, t1.K) Key2,
t2.V as Value2
from
(select * from t where id = (select C_id from Cust1)) t1
full outer join (select * from t where id = (select C_id from Cust2)) t2
on t1.k = t2.k
to test I used
with
Cust1 as (select 'C1' as C_id from DUAL)
,Cust2 as (select 'C2' as C_id from DUAL)
,t as (
select 'C1' ID, 'AskPhoneNo' K, 'TRUE' V union
select 'C1', 'Website', 'C1Website.com' union
select 'C1', 'Report', 'TRUE' union
select 'C2', 'AskPhoneNo', 'TRUE' union
select 'C2', 'Report', 'FALSE' union
select 'C2', 'AskAddress', 'TRUE')
select (select C_id from Cust1) ID1,
coalesce(t1.K, t2.K) Key1,
t1.V as Value1,
(select C_id from Cust2) ID2,
coalesce(t2.K, t1.K) Key2,
t2.V as Value2
from
(select * from t where id = (select C_id from Cust1)) t1
full outer join (select * from t where id = (select C_id from Cust2)) t2
on t1.k = t2.k
Upvotes: 0
Reputation: 3811
you can use full outer join + nvl
CREATE TABLE T
("CustomerID" varchar2(2), "Key" varchar2(10), "Value" varchar2(13));
INSERT ALL
INTO T ("CustomerID", "Key", "Value")
VALUES ('C1', 'AskPhoneNo', 'TRUE')
INTO T ("CustomerID", "Key", "Value")
VALUES ('C1', 'Website', 'C1Website.com')
INTO T ("CustomerID", "Key", "Value")
VALUES ('C1', 'Report', 'TRUE')
INTO T ("CustomerID", "Key", "Value")
VALUES ('C2', 'AskPhoneNo', 'TRUE')
INTO T ("CustomerID", "Key", "Value")
VALUES ('C2', 'Report', 'FALSE')
INTO T ("CustomerID", "Key", "Value")
VALUES ('C2', 'AskAddress', 'TRUE')
SELECT * FROM dual;
select
nvl(T1."CustomerID",'C1') as CustomerID,
nvl(T1."Key",T2."Key") as Key,
T1."Value" as Value,
nvl(T2."CustomerID",'C2') as CustomerID,
nvl(T2."Key",T1."Key") as Key,
nvl(T1."Key",null) as Value
from (
select * from T where "CustomerID" = 'C1'
) T1
full outer join (
select * from T where "CustomerID" = 'C2'
) T2
on T1."Key" = T2."Key"
CUSTOMERID | KEY | VALUE | CUSTOMERID | KEY | VALUE :--------- | :--------- | :------------ | :--------- | :--------- | :--------- C1 | AskPhoneNo | TRUE | C2 | AskPhoneNo | AskPhoneNo C1 | Report | TRUE | C2 | Report | Report C1 | AskAddress | null | C2 | AskAddress | null C1 | Website | C1Website.com | C2 | Website | Website
db<>fiddle here
Upvotes: 0
Reputation: 19386
Are you going to compare data only between 2 customers?
Select
cust1, key1, val1,
cust2, key2, val2
from
(select CustomerID cust1, key key1, value val1
from myTable
where CustomerID = 1) c1 inner join
(select CustomerID cust2, key key2, value val2
from myTable
where CustomerID = 2) c2 on
c1.key1 = c2.key2;
I hope, this is self-explanatory. But this particular SQL will work only if you have cust1 and cust2 values. If some of them missing, we need use left and right joins, or a FULL JOIN
Upvotes: 0
Reputation:
There are two problems with your required output. First, there's no point in the constant columns (with values C1 and C2 respectively), and there's no reason to repeat the key names. Second, your output seems to show ALL the rows, not just the "differences". If you need to show ALL the rows (whether the values are the same or different), just remove the where
clause below.
with
test_data(customer_id, key, value) as (
select 'C1', 'AskPhoneNo', 'TRUE' from dual union all
select 'C1', 'Website' , 'C1Website.com' from dual union all
select 'C1', 'Report' , 'TRUE' from dual union all
select 'C2', 'AskPhoneNo', 'TRUE' from dual union all
select 'C2', 'Report' , 'FALSE' from dual union all
select 'C2', 'AskAddress', 'TRUE' from dual union all
select 'C3', 'AskAddress', 'FALSE' from dual union all
select 'C3', 'Report' , 'TRUE' from dual union all
select 'C3', 'Website' , 'C3web.edu' from dual
)
-- End of simulated inputs (for testing only, not part of the solution!)
select key, c1_value, c2_value
from test_data
pivot (max(value) for customer_id in ('C1' as c1_value, 'C2' as c2_value))
where decode(c1_value, c2_value, 0, 1) = 1 -- If needed
order by key -- If needed
;
KEY C1_VALUE C2_VALUE
---------- ------------- -------------
AskAddress TRUE
Report TRUE FALSE
Website C1Website.com
Upvotes: 1