SELECT contactid, firstname, email, phone
FROM vtiger_contactscf t1
WHERE email
IN (SELECT email FROM vtiger_contactscf WHERE CHAR_LENGTH(email)>0 GROUP BY email HAVING count(*)>1)
OR phone
IN (SELECT phone FROM vtiger_contactscf WHERE CHAR_LENGTH(phone)>0 GROUP BY phone HAVING count(*)>1)
The above SQL query produces a table with all of the contacts i have which have the same email or phone number as another contact.
For each contact I get the contactid, firstname, phone, and email. However, I also want to JOIN the lastname. But lastname data is stored in a different table. That table also has contactid so i could use it for the JOIN ON. But when I simply add a JOIN t2 ON t1.contactid=t2.contactid it still doesn't work.
Full code with the join statement:
SELECT t1.contactid, t1.firstname, t2.lastname t1.email, t1.phone
FROM vtiger_contactscf t1
WHERE t1.email
IN (SELECT email FROM vtiger_contactscf WHERE CHAR_LENGTH(email)>0 GROUP BY email HAVING count(*)>1)
OR t1.phone
IN (SELECT phone FROM vtiger_contactscf WHERE CHAR_LENGTH(phone)>0 GROUP BY phone HAVING count(*)>1)
JOIN vtiger_contactsdetails t2 ON t1.contactid = t2.contactid
What am I doing wrong?
JOIN is an operator that belongs in the FROM clause:
SELECT c.contactid, c.firstname, cd.lastname c.email, c.phone
FROM vtiger_contactscf c JOIN
vtiger_contactsdetails cd
ON c.contactid = cd.contactid
WHERE c.email IN (SELECT c2.email
FROM vtiger_contactscf c2
WHERE CHAR_LENGTH(c2.email) > 0
GROUP BY c2.email
HAVING count(*) > 1
) OR
c.phone IN (SELECT c2.phone
FROM vtiger_contactscf c2
WHERE CHAR_LENGTH(c2.phone) > 0
GROUP BY phone
HAVING count(*) > 1
);
That said, this seems a little strange. You have two tables with essentially the same primary key? Is it possible that one contactid could have multiple rows in the details table? If so, the above logic may not work, because the multiple records could have the same phone number or email.
You can fix this and simplify the query using EXISTS:
SELECT c.contactid, c.firstname, cd.lastname c.email, c.phone
FROM vtiger_contactscf c JOIN
vtiger_contactsdetails cd
ON c.contactid = cd.contactid
WHERE EXISTS (SELECT 1
FROM vtiger_contactscf c2
WHERE CHAR_LENGTH(c2.email) > 0 AND c2.email = c.email AND c2.contactid <> c.contactid
) OR
EXISTS (SELECT c2.phone
FROM vtiger_contactscf c2
WHERE CHAR_LENGTH(c2.phone) > 0 AND c2.phone = c.phone AND c2.contactid <> c.contactid
);
This may not look much simpler, but EXISTS can take advantage of an index on vtiger_contactscf(phone, contactid) and vtiger_contactscf(email, contactid).
Related
I keep getting error code #1241. I have been looking to find an answer but I can't find an answer that helped me.
Here is my code:
SELECT name, address, city, phone
FROM customer
WHERE customer.ID IN (
SELECT customer.ID, COUNT(*) AS amount_reservations
FROM customer, (
SELECT ID
FROM customer, reservations
WHERE rent_time = 'weekend' AND
ID = customer_ID
) AS foo
WHERE customer.ID = foo.ID
GROUP BY customer.ID
HAVING amount_reservations > 1
)
The subquery SELECT customer.ID, COUNT(*) AS amount_reservations should have a SINGLE column, not two.
Change it as:
SELECT name, address, city, phone
FROM customer
WHERE customer.ID IN (
SELECT customer.ID
FROM customer, (
SELECT ID FROM customer, reservations
WHERE rent_time = 'weekend' AND ID = customer_ID
) AS foo
WHERE customer.ID = foo.ID
GROUP BY customer.ID HAVING count(*) > 1
)
I'd highly recommend rewriting your query. Remove the subqueries -- they aren't needed. Then use explicit joins instead of commas.
select c.id, c.name, c.address, c.city, c.phone
from customer c
join reservations r on c.id = r.customer_id
where r.rent_time = 'weekend'
group by c.id, c.name, c.address, c.city, c.phone
having count(*) > 1
If you want to use in, you can radically simplify the query:
SELECT c.name, c.address, c.city, c.phone
FROM customer c
WHERE c.ID IN (SELECT r.customer_id
FROM reservations r
WHERE r.rent_time = 'weekend'
GROUP BY r.customer_id
HAVING COUNT(*) > 1
) ;
Notes:
Never use commas in the FROM clause. Always use proper, explicit, standard JOIN syntax.
Use table aliases and qualified column names for all column references.
You don't need a JOIN in the subquery, because you have the customer id in the reservations table.
SELECT t.id
, t.department
, t.owner
, t.client
, u.username as owner_name
, c.name as catagery
, d.dept_name as deptname
, t.periority
, t.status
, t.estimate
, cl.takeaway_name
from tbl_task t
JOIN tbl_user u
ON u.id = t.owner
JOIN tbl_task_catagery c
ON c.id = t.catagery
JOIN tbl_department d
ON d.id = t.department
JOIN tbl_clients cl
ON cl.id = t.client
and t.status = 0
and (t.id in (select task_id
from tbl_task_note tn
where tn.user_id = '69'
and tn.id in (select max(id)
from tbl_task_note tt
where tt.task_id = tn.task_id
)
)
)
order by t.id
Note : The above query is used for check users hold tasks. tbl_task_note table is used for check task notes for separate users task.
With this query you will get the task that have the last task_note registered, including the user, departament, client, and some other.
If it is what you need you can just do this.
select
t.id,
t.department,
t.owner,
t.client,
u.username as owner_name,
c.name as catagery,
d.dept_name as ptname,
t.periority,
t.status,
t.estimate,
cl.takeaway_name
from tbl_task t
INNER JOIN tbl_user u ON u.id=t.owner
INNER JOIN tbl_task_catagery c ON c.id=t.catagery
INNER JOIN tbl_department d ON d.id=t.department
INNER JOIN tbl_clients cl ON cl.id=t.client and t.status=0
INNER JOIN (select * from tbl_task_note where id =
(select max(id) from tbl_task_note)
)tb on tb.task_id = t.id
order by t.id
That way you can improve your query.
You shoud also ensure that your keys compared are foreign keys to get faster consults.
I have to do sum from 2 different tables and show it using MySQL:
total comments from table 1, total comments from table 2: What i have tried so far is,
SELECT u.name as name, u.username as username,
( SELECT SUM(total) FROM (SELECT (COUNT(nc.id)) as total FROM table1 as nc WHERE nc.user_id = u.id) UNION ALL (SELECT COUNT(pc.id) AS total FROM table2 pc WHERE pc.user_id = u.id) as finalTotal ) as total_comments
FROM user as u
GROUP BY u.id
It is giving me this error:
Every derived table must have its own alias
If I understand what you need, you have to modify the query like this :
select u.name,u.username,total as total_comments
from user as u
left join (
select id,sum(total) as total
from(
select nc.id,count(1) as total
from table1 as nc
group by nc.id
union all
select pc.id,count(1) as total
from table2 as pc
group by pc.id
) as t group by id
) comments on comments.id = u.id
Before UNION ALL put alias like you giving for all..
SELECT u.name as name, u.username as username,
( SELECT SUM(total) FROM (SELECT (COUNT(nc.id)) as total FROM table1 as nc WHERE nc.user_id = u.id) as vr UNION ALL (SELECT COUNT(pc.id) AS total FROM table2 pc WHERE pc.user_id = u.id) as finalTotal ) as total_comments
FROM user as u
GROUP BY u.id
SELECT u.name as name, u.username as username,
( SELECT SUM(total) FROM
(SELECT (COUNT(nc.id)) as total FROM table1 as nc WHERE nc.user_id = u.id
UNION ALL SELECT COUNT(pc.id) AS total FROM table2 pc WHERE pc.user_id = u.id) as finalTotal ) as total_comments
FROM user as u
GROUP BY u.id
Remove brackets before and after UNION ALL and check.
Welcome,
I have 2 tables int_client AND int_client_bank.
In first important columns: client_id, firstname, lastname, country, email, status.
In the second: client_id, status.
I need to display all records: firstname, lastname, country, e-mail WHERE status='25' of the first column (except those records where client_id occurs in the second table).
If client_id occurs in the second table is skipping statuses of the first column, and displays only status='25' in secound table.
Sb can help me?
edit:
SELECT firstname, lastname, country, email, COALESCE(b.status, a.status) status
FROM int_client a
LEFT JOIN int_client_back b USING (client_id)
WHERE
(b.status IS NULL and a.status='25')
OR b.status IS NOT NULL;
This is good code, but i need show only records there have status='25' in column B, and if a.client_id != b.client_id, i need show records there have status='25' in column A
Sb, help?
LEFT JOIN with COALESCE() should do:
SELECT firstname, lastname, country, email, COALESCE(b.status, a.status) status
FROM int_client a
LEFT JOIN int_client_back b USING (client_id)
WHERE
(b.status IS NULL and a.status='25')
OR b.status IS NOT NULL;
This select query should work:
SELECT t1.first_name,t1.last_name,t1.country,t1.email FROM int_client AS t1, int_client_bank AS t2
WHERE t1.client_id = t2.client_id AND t1.status = 25;
If I understand correctly, you want all records from int_client where status is "25". However, if another status exists in int_client_bank, then you want to show that status.
select c.first_name, c.last_name, c.email, c.country,
coalesce(cb.status, c.status)
from int_client c left join
int_client_bank cb
on cb.client_id = c.client_id
where c.status = 25;
Below is the query which will do the trick for you.
SELECT client_id, firstname, lastname, country, email, status FROM int_client as ic LEFT JOIN int_client_back icb ON ic.client_id=icb.client_id WHERE ic.status=25
SELECT DISTINCT firstname, lastname, country, email,
a.status as status_a, b.status as status_b, if(b.status is NULL, a.status, b.status) as final_status
FROM int_client a
LEFT JOIN int_client_bank b USING (client_id)
WHERE
if(b.status is NULL, a.status, b.status) = '25'
I have a design like this
accounts(id, username, email, password, ..)
admin_accounts(account_id, ...)
user_accounts(account_id, ....)
premium_accounts(account_id, ....)
id is the primary key in accounts
account_id is a foreign(references id on accounts table) and primary key in these three tables(admin, user, premium)
Knowing the id how can I find which type this user is with only one query? Also knowing that an id can only exists in one of the three tables(admin, user, premium)
Using case:
select
a.id,
case
when aa.account_id is not null then 'admin_accounts'
when ua.account_id is not null then 'user_accounts'
when pa.account_id is not null then 'premium_accounts'
else
'No detail found'
end as found_in
from
accounts a
left join admin_accounts aa on aa.account_id = a.id
left join user_accounts ua on ua.account_id = a.id
left join premium_accounts pa on pa.account_id = a.id
/*where -- In case you want to filter.
a.id = ....*/
using union
select
id,
found_in
from
(select account_id as id, 'admin_accounts' as found_in
from admin_accounts aa
union all
select account_id, 'user_accounts'
from user_accounts ua
union all
select account_id, 'premium_accounts'
from premium_accounts pa) a
/*where -- In case you want to filter.
a.account_id = ....*/
If you use UNION you can try applying a solution proposed here - mysql return table name
You can use union query like
(select id, 'admin' as user_type from account inner join admin_accounts) UNION
(select id, 'user' as user_type from account inner join user_accounts) UNION
(select id, 'premium' as user_type from account inner join premium_accounts);