CTE passing multiple subqueries - mysql

This is an extension to my previous post.
WITH cte1 AS (
SELECT * FROM Combination
WHERE Col1 = 'val' and city='karim'),
cte2 AS (
SELECT * FROM Combination
WHERE Col1 = 'val2' and city='karim')
SELECT CONCAT(cte1.Col2, cte2.Col2) AS Result
FROM cte1 CROSS JOIN cte2;
col1
col2
City
Val
145
Telang
val2
13
Telang
val2
25
Telang
val
146
karim
val2
124
karim
val2
56
karim
Output:
Result
14513
14525
146124
14656
There are multiple cities.I wanted to get combinations only for the values existing in the cities
Tried something like this, but does not work.
SELECT * FROM Combination
WHERE Column1 = 'value' and city IN(select city from Combinations);

Use an INNER self join of the table:
SELECT CONCAT(c1.Col2, c2.Col2) AS Result
FROM Combination c1 INNER JOIN Combination c2
ON c2.city = c1.city
WHERE c1.Col1 = 'val' AND c2.Col1 = 'val2';

Related

Match duplicate value from 2 colums and 1 unique value from 1 column mysql

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.

How can I get the result by only one sql in MySQL

There two mysql table just like table1 and table2. I want get the result by one sql.
#table1
c1 c2 //clomun
a 10
b 20
c 30
#table2
c1 c2
a 11
b 21
e 99
I want get the result like below.
# result
c1 c2
a 21
b 41
c 30
e 99
This should work:
select c1, sum(c2) from
(
select c1, c2 from table1
union all
select c1, c2 from table2
) as total
group by c1
Please note that if the columns names are not identical, you will need to give them identical alias names as below:
select column1, sum(column2 ) from
(
select c1 as column1, c2 as column2 from table1
union all
select c1 as column1, c2 as column2 from table2
) as total
group by column1

Filter Results in SQL

Suppose I have a table
id value
------ ---------
10 123
10 422
11 441
11 986
12 674
13 648
I need a query which will return only those id's which have 2 or more values associated with them. So, in that case it will only return ID 10 & 11, but i need al the records.
so the result looks like:
id value
------ ---------
10 123
10 422
11 441
11 986
Thank you.
select a2.*
from MyTable a2
inner join
(
select a1.id
from MyTable a1
group by a1.id
having count(*) > 1
) a3
on a3.id = a2.id
Assuming a UNIQUE KEY can be formed on (id,value)...
SELECT DISTINCT x.*
FROM my_table x
JOIN my_table y
ON y.id = x.id
AND y.value <> x.value
If a UNIQUE KEY cannot be formed on (id,value), then this isn't really a table in a strict RDBMS sense.
You can use this query :
SELECT * from table where id in
( SELECT id FROM table group by id having count(id) > 1 )
With mysql 8+ or mariadb 10.2+, you would use the count window function:
select id, value
from (
select id, value, count(id) over (partition by id) as num_values
from sometable
) foo
where num_values > 1;

Id Column having diffrent values in another column need show with specilal value

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

MySQL select unique records on two columns

How do I select rows where two columns are unique?
Given table
id col1 col2
1 a 222
2 b 223
3 c 224
4 d 224
5 b 225
6 e 226
How do remove the duplicates in col1 and the duplicates in col2, to get rows unique to whole table,
So that result is
id col1 col2
1 a 222
6 e 226
Is there a better way than using sub queries?
SELECT * FROM table WHERE id
IN (SELECT id FROM table WHERE col1
IN (SELECT col1 FROM table GROUP BY col1 HAVING(COUNT(col1)=1))
GROUP BY col2 HAVING(COUNT(col2)=1))
This should work using exists:
select *
from yourtable y
where not exists (
select 1
from yourtable y2
where y.id != y2.id
and (y.col1 = y2.col1
or y.col2 = y2.col2))
SQL Fiddle Demo
Here's an alternative solution using an outer join as I've read mysql sometimes doesn't do well with exists:
select *
from yourtable y
left join yourtable y2 on y.id != y2.id
and (y.col1 = y2.col1
or y.col2 = y2.col2)
where y2.id is null;
More Fiddle
You can also do this by aggregating along each dimension:
select t.*
from table t join
(select col1
from table t
group by col1
having count(*) = 1
) t1
on t.col1 = t1.col1 join
(select col2
from table t
group by col2
having count(*) = 1
) t2
on t.col2 = t2.col2;
This method seems like a very direct translation of the user requirements.