MYSQL count number of times value is in 3 columns - mysql

I have a query that gets some data about customers. This customers can have three phone numbers and these can be repeated.
To count the number of times that these phones are repeated a partner have create a subselect:
(select count(*)
from TABLE_A as k
where (k.phone=a.phone or k.phone2=a.phone or k.phone3=a.phone)
and k.id!=a.id) as repetitionsPhone1
This is inside a bigger select like this:
SELECT a.*,c.*,b.*,
(
select count(*)
from TABLE_A as k
where (k.phone=a.phone or k.phone2=a.phone or k.phone3=a.phone)
and k.id!=a.id
) as repetitionsPhone1
FROM a
left join c on a.id=c.id
left join b on a.id=b.id
This query takes for 50 rows about 30 seconds, and it should return about 2000 rows every single day.
To optimize this I use explain and I see that this subquery was the problem so I searched and I tried this:
SELECT phn,sum(count) as phoneRepetitions
from (
select k.phone1 as phn, count(*) as count
from k
group by k.phone1
UNION
select k.phone2 as phn,count(*) as count
from k
group by k.phone2
UNION
select k.phone3 as phn,count(*) as count
from k
group by k.phone3
) as aux
group by phn
And this returns #1062 MYSQL error: Duplicate entry for key 'distinct key'
First of all I would like to solve this problem. Anyone knows what is happening? This error seems logic in an insert statement, but in select?
And later, this will help to improve the big select that I must optimize? I will have to do this for the three columns.
Thank you.

SELECT count(*) from
(SELECT phones1 FROM k
union
SELECT phones2 from k
union
SELECT phones3 from k)
AS SumCountPhones
This seemed to work for me.
Solution as per How do I add two count(*) results together on two different tables?
You can keep stacking the unions.

SELECT
COUNT(*) AS CountOf FROM
table1
INNER JOIN
table2
GROUP BY phone1 , phone2 , phone3
HAVING COUNT(*) > 1

Related

How to duplicate returning values from a query in MySQL

When I use this I Get the table two times but I want each value duplicated before the next value comes
SELECT *
FROM student
WHERE major LIKE 'C%'
UNION ALL
SELECT *
FROM student
WHERE major LIKE 'C%';
You can use a union all. A union will not work, because it will eliminate duplicates. Another way is a cross join:
select
*
from
students t1 cross join
(select 1 as n union all select 2) n
WHERE major LIKE 'C%'
order by id;

How to get rows even if count is 0? Only 1 table

I want the count even if the count is 0. My current query is
SELECT `id`,count(0) as `fetchpc` FROM `user` WHERE pid in('4,6,7,8') GROUP BY `id`
But it returns only those id where count is greater than 0
Edit:
the values used for in('4,6,7,8') are first fetched from database in another query. And then using a script rows are converted to 4,6,7,8.
So all the values are present in the database.
Also it is possible that the values returned can go upto 100+ values.
You could left join this query on a "fictive" query that queries these IDs as literals:
SELECT ids.id, COALESCE(cnt, 0)
FROM (SELECT 4 AS id
UNION ALL
SELECT 6 AS id
UNION ALL
SELECT 7 AS id
UNION ALL
SELECT 8 AS id) ids
LEFT JOIN (SELECT id, COUNT(*) AS cnt
FROM fetchpc
GROUP BY id) t ON t.id = ids.id
You can use a derived table. I would recommend:
SELECT i.id, COUNT(u.id) as fetchpc
FROM (SELECT 4 as id UNION ALL
SELECT 6 as id UNION ALL
SELECT 7 as id UNION ALL
SELECT 8 as id
) i LEFT JOIN
`user` u
ON u.id = i.id
GROUP BY i.id;
From a performance perspective, this is much better than aggregating first (in a subquery) and then joining. Basically, the aggregation (in that case) has to aggregate all the data and afterwards filter out the unnecessary rows.
This formulation filters the rows first, which should speed the aggregation.

Select distincts of same column in mutiple tables sql

SQL novice here.
I have this schema:
What I need in plain English is:
"Out of the 2 columns, make one above the other in one column, and then count how many distincts values there is"
I've tried
SELECT COUNT (DISTINCT uid ) from nodes UNION SELECT COUNT (DISTINCT uid) from ways ;
SELECT distinct nodes.uid from nodes JOIN ways on nodes.uid = ways.uid ;
sqlite> SELECT COUNT (DISTINCT uid ) from nodes UNION SELECT COUNT (DISTINCT uid) from ways ;
1195
2182
sqlite> SELECT uid from nodes FULL OUTER JOIN ways on nodes.uid = ways.iud ;
Error: RIGHT and FULL OUTER JOINs are not currently supported
SELECT COUNT (DISTINCT iud) FROM (SELECT DISTINCT uid from nodes as uid UNION SELECT DISTINCT uid from ways as uid as subq);
SELECT count (distinct nodes.uid) from nodes JOIN ways on nodes.uid = ways.uid ;
takes ages and i'm not sure nodes.uid = ways.uid is the correct way to go
Any idea ?
I think i got it
SELECT COUNT (DISTINCT uid) from (SELECT DISTINCT uid from nodes UNION SELECT DISTINCT uid from ways) as subq ;
Since UNION returns a distinct set of the joining tables you dont need to use the DISTINCT keyword
SELECT COUNT(uid) Cnt
FROM (
SELECT uid
FROM nodes
UNION
SELECT uid
FROM ways
) t

Mysql Union in different columns

I have the following query
SELECT *
FROM(
(SELECT
MAX(c.start_time) as start_1
FROM
c1 c)
UNION ALL
(SELECT
MAX(cc.created_at) as ccmax
FROM
cc1)
) as t
I'd like to have the result in a table with 2 columns start_1 and cmax instead of the single column I get with all the different results listed.
How should I do it? I ended up in a subselect believing this would have done the job.
For the data to be in two columns you would have to use a sub select.
SELECT
MAX(c1.start_time) as start_1, (SELECT MAX(cc1.created_at) FROM cc1) as ccmax
FROM c1

MySQL, merging 2 or more tables before execute SELECT DISTINCT query?

I want to calculate how many unique logins from 2 (or probably more tables).
I tried this:
SELECT count(distinct(l1.user_id))
FROM `log_1` l1
LEFT JOIN `log_2` l2
ON l1.userid = l2.userid;
But it gives me result of l1. If I didn't put l1 on li.userid (distinct), it said "ambiguous".
How do I combine the table, and then select unique login of the combined table?
EDIT:
Tested: I test the count(distinct(l1.userid)) and count(distinct(l2.userid)). It gives me different result
If you are using LEFT JOIN then you will get at least one row in the combined result for each row in l1, so the join is entirely unnecessary if you just want a distinct count. This would give you the same result as your query:
SELECT count(distinct(l1.user_id))
FROM `log_1` l1
Perhaps you want an INNER JOIN or UNION instead? A UNION will count a user if they appear in either table. An INNER JOIN will count them only if they appear in both tables. Here's an example of the UNION:
SELECT count(*) FROM (
SELECT distinct(user_id) FROM `log_1`
UNION
SELECT distinct(user_id) FROM `log_2`
) T1