I have this table, here is my db Fiddle
CREATE TABLE table1 (
`ID` VARCHAR(100),
`Val` VARCHAR(100),
`Val2` VARCHAR(100),
`Val3` VARCHAR(100)
);
INSERT INTO table1
(`ID`, `Val`, `Val2`, `Val3`)
VALUES
('1','100','200','90'),
('2','100','200','10'),
('3','100','200','20'),
('4','20','100','55'),
('5','20','100','10'),
('6','112','100','20'),
('7','112','100','20'),
('8','90','200','90'),
('9','30','90','180'),
('10','30','90','29');
I want the result with this condition
Val had to be duplicate AND
Val2 had to be duplicate AND
After i got the duplicate value, now i need to check the val3 from the duplicate value if the value of val3 had unique value from the previous aggregate
i tried with this query
SELECT
t1.*
FROM
table1 t1
WHERE
EXISTS (
SELECT
1
FROM
table1
WHERE
ID <> t1.ID
AND Val = t1.Val
AND Val2 = t1.Val2
)
AND NOT EXISTS (
SELECT
1
FROM
table1
WHERE
Val = t1.Val
AND Val2 = t1.Val2
AND Val3 IN (
SELECT Val3
FROM table1
GROUP BY Val3
HAVING count( * ) > 1
)
)
I expect the result would be like this
ID Val Val2 Val3
1 100 200 90
2 100 200 10
3 100 200 20
4 20 100 55
5 20 100 10
9 30 90 180
10 30 90 29
BUt i got the result like this
ID Val Val2 Val3
9 30 90 180
10 30 90 29
Sample 2
INSERT INTO table1
(`ID`, `Val`, `Val2`, `Val3`)
VALUES
('1','100','200','90'),
('2','100','200','10'),
('3','100','200','20'),
('19','100','200','20'),
('4','20','100','55'),
('5','20','100','10'),
('6','112','100','20'),
('7','112','100','20'),
('8','90','200','90'),
('9','30','90','180'),
('10','30','90','29');
Expected result 2
ID Val Val2 Val3
1 100 200 90
2 100 200 10
4 20 100 55
5 20 100 10
9 30 90 180
10 30 90 29
dbfiddle 2
Sample 3
INSERT INTO table1
(`ID`, `Val`, `Val2`, `Val3`)
VALUES
('1','100','200','aa'),
('2','100','200','aa'),
('3','100','200','aa'),
('19','100','200','ab'),
('4','20','100','SD2'),
('5','20','100','SD1'),
('6','112','100','aa'),
('7','112','100','ab'),
('8','90','200','aa'),
('9','30','90','SF2'),
('10','30','90','SF1');
Expected result 3
ID Val Val2 Val3
4 20 100 SD2
5 20 100 SD1
6 112 100 aa
7 112 100 ab
9 30 90 SF2
10 30 90 SF1
Some people might be confused with sample 3, so here is a notes for sample 3 :
For this case, ID 19 in sample 3 had same value with column val and val2 for id 1, 2, 3 ( 100 and 200), but these id (1, 2, 3) had same aa value in val3, so id 1,2,3 must be excluded, because these id did not match with last condition (val, val2, val3) is unique. ID 19 is fine but val dan val2 column that had duplicate value which is id 1,2,and 3 had already excluded, it makes id 19 had no duplicate value for both column val and val2. if there was another data like '200','100','200','ae' in sample 3, the id 19 will included in result because it has duplicate value beside id 1,2,and 3.
for sample 3 ID 19 will be included if the data in table1 were like this
Sample 3 ( different case )
INSERT INTO table1
(`ID`, `Val`, `Val2`, `Val3`)
VALUES
('1','100','200','aa'),
('2','100','200','aa'),
('3','100','200','aa'),
('19','100','200','ab'),
('200','100','200','ae'),
('4','20','100','SD2'),
('5','20','100','SD1'),
('6','112','100','aa'),
('7','112','100','ab'),
('8','90','200','aa'),
('9','30','90','SF2'),
('10','30','90','SF1');
The expected result will be like this
ID Val Val2 Val3
4 20 100 SD2
5 20 100 SD1
19 100 200 ab
200 100 200 ae
6 112 100 aa
7 112 100 ab
9 30 90 SF2
10 30 90 SF1
Join the table to the queries that apply your conditions:
select distinct t.*
from (
select val, val2
from table1
group by val, val2
having count(*) > 1
) t1
inner join (
select val, val2, val3
from table1
group by val, val2, val3
having count(*) = 1
) t2
on t2.val = t1.val and t2.val2 = t1.val2
inner join (
select val, val2, val3
from table1
group by val, val2, val3
having count(*) = 1
) t3
on t3.val = t1.val and t3.val2 = t1.val2 and t3.val3 <> t2.val3
inner join table1 t on t2.val = t.val and t2.val2 = t.val2 and t.val3 in (t2.val3, t3.val3)
See demo1, demo2, demo3, demo4.
As I understand your question, you want rows whose (val, val2) tuple is not unique, and whose (val, val2, val3) is unique.
Here is one way to express this by filtering the dataset with correlated subquery:
select t1.*
from table1 t1
where
(
select count(*)
from table1 t2
where t2.val = t1.val and t2.val2 = t1.val2
) > 1
and (
select count(*)
from table1 t2
where t2.val = t1.val and t2.val2 = t1.val2 and t2.val3 = t1.val3
) = 1
order by id
For performance, consider an index on (val, val1, val2) (the ordering of columns in the index matters here).
If you are lucky enough to be running MySQL 8.0, this can be phrased more simply and more efficiently using window functions:
select id, val, val2, val3
from (
select
t1.*,
count(*) over(partition by val, val2) cnt_1,
count(*) over(partition by val, val2, val3) cnt_2
from table1 t1
) t
where cnt_1 > 1 and cnt_2 = 1
As #GMB told in rather simplified manner in his answer, you want rows whose (val, val2) tuple is not unique, and whose (val, val2, val3) is unique.
Following query should accomplish that very easily:
select t.*
from table1 t
inner join
(
select t1.val, t1.val2
from table1 t1
inner join
(select val,val2,val3
from table1
group by val,val2,val3
having count(val3) = 1
) t2
on t1.val = t2.val and t1.val2 = t2.val2 and t1.val3 = t2.val3
group by t1.val, t1.val2
having count(distinct t1.id) > 1
) tmp
on tmp.val = t.val and tmp.val2 = t.val2
inner join
(select val,val2,val3
from table1
group by val,val2,val3
having count(val3) = 1
) t3
on t.val = t3.val and t.val2 = t3.val2 and t.val3 = t3.val3
Please find the fiddle link for Sample1, Sample2, Sample3 and Sample4.
I have one Table Test in this table Id column, FuelId and FuelDesc columns are there.values are like below table,Based on first three columns i need to create out put table like below please help me to get.
ID FuelID FuelDesc
100 01 Elec
101 02 Gas
102 02 Gas
100 02 Gas
101 01 Elec
103 01 Elec
O/P:-
ID Pamenttype
100 Both
101 Both
102 Gas
103 Elec
You can use a CASE expression, with the help of COUNT and MAX functions:
SELECT
ID,
PaymentType = CASE WHEN COUNT(FuelId) > 1 THEN 'Both' ELSE MAX(FuelDESC) END
FROM test
GROUP BY ID
SELECT ID, CASE WHEN rowCount = 1 THEN FuelDesc ELSE 'Both' END AS Pamenttype
FROM
(SELECT ID, MAX(FuelDesc) AS FuelDesc, COUNT(*) AS rowCount
FROM mytable
GROUP BY ID)
You can define Both as having one record with FuelID = '01' and another with FuelID = '02'. Assuming {ID, FuelID} is unique in table Test:
with BothPaymentTypes as (
select t1.ID
from Test t1
join Test t2 on t1.ID = t2.ID
where t1.FuelID = '01'
and t2.FuelID = '02'
)
select ID, 'Both' as Pamenttype
from BothPaymentTypes
union all
select ID, FuelDesc
from Test
where ID not in (select ID from BothPaymentTypes)
[SQL Fiddle Demo]
Alternatively, you can avoid the self-join with a COUNT and HAVING clause - again assuming {ID, FuelID} is unique:
with BothPaymentTypes as (
select ID
from Test
group by ID
having count(*) = 2
)
select ID, 'Both' as Pamenttype
from BothPaymentTypes
union all
select ID, FuelDesc
from Test
where ID not in (select ID from BothPaymentTypes)
[SQL Fiddle Demo]
WITH fuelCount
AS
(
SELECT ID, COUNT(FuelID) AS fuelCount
FROM Test GROUP BY ID
)
SELECT fc.ID,
CASE
WHEN fc.fuelCount > 1 THEN 'BOTH'
ELSE (SELECT t.FuelDesc FROM Test t WHERE t.ID = fc.ID)
END AS Pamenttype
FROM fuelCount fc