I have a table in which a field contains an integer or NULL.
parent_id
2
4
6
NULL
NULL
45
2
How would I go about adding an IFNULL statement so that ans_count will be populated with 0 instead of NULL?
Here is my SQL code:
...
(SELECT parent_id AS pid, COUNT(*) AS ans_count
FROM qa
GROUP BY parent_id) AS n
UPDATE
Full SQL below - thanks to all for your patience.
SELECT *
FROM qa
JOIN user_profiles
ON user_id = author_id
LEFT JOIN (SELECT cm_id,
cm_author_id,
id_fk,
cm_text,
cm_timestamp,
first_name AS cm_first_name,
last_name AS cm_last_name,
facebook_id AS cm_fb_id,
picture AS cm_picture
FROM cm
JOIN user_profiles
ON user_id = cm_author_id) AS c
ON id = c.id_fk
LEFT JOIN (SELECT parent_id AS pid, COUNT(*) AS ans_count
FROM qa
GROUP BY parent_id) AS n
ON id = n.pid
WHERE id LIKE '%'
ORDER BY id DESC
EDIT: NEW INFO BASED ON FULL QUERY
The reason the counts can be null in the query you specify is because a left join will return nulls on unmatched records. So the subquery itself is not returning null counts (hence all the responses and confusion). You need to specify the IFNULL in the outer-most select, as follows:
SELECT qa.*, user_profiles.*, c.*, n.pid, ifnull(n.ans_count, 0) as ans_count
FROM qa
JOIN user_profiles
ON user_id = author_id
LEFT JOIN (SELECT cm_id,
cm_author_id,
id_fk,
cm_text,
cm_timestamp,
first_name AS cm_first_name,
last_name AS cm_last_name,
facebook_id AS cm_fb_id,
picture AS cm_picture
FROM cm
JOIN user_profiles
ON user_id = cm_author_id) AS c
ON id = c.id_fk
LEFT JOIN (SELECT parent_id AS pid, COUNT(*) AS ans_count
FROM qa
GROUP BY parent_id) AS n
ON id = n.pid
WHERE id LIKE '%'
ORDER BY id DESC
OLD RESPONSE
Can you explain in more detail what you are seeing and what you expect to see? Count can't return NULLs.
Run this set of queries and you'll see that the counts are always 2. You can change the way the NULL parent_ids are displayed (as NULL or 0), but the count itself will always return.
create temporary table if not exists SO_Test(
parent_id int null);
insert into SO_Test(parent_id)
select 2 union all select 4 union all select 6 union all select null union all select null union all select 45 union all select 2;
SELECT IFNULL(parent_id, 0) AS pid, COUNT(*) AS ans_count
FROM SO_Test
GROUP BY IFNULL(parent_id, 0);
SELECT parent_id AS pid, COUNT(*) AS ans_count
FROM SO_Test
GROUP BY parent_id;
drop table SO_Test;
I didn't test this, but I think it will work
(SELECT IF( parent_id IS NULL, 0, parent_id) AS pid, COUNT(*) AS ans_count
FROM qa
GROUP BY parent_id) AS n
Simply wrap it around your statement:
IFNULL(
(SELECT parent_id AS pid, COUNT(*) AS ans_count
FROM qa
GROUP BY parent_id)
, 0
) AS n
Have you tried just counting the parent_id's?
(SELECT parent_id AS pid, COUNT(parent_id) AS ans_count
FROM qa
GROUP BY parent_id)
SELECT IFNULL(parent_id, 0) AS pid, COUNT(IFNULL(parent_id, 0)) AS ans_count
FROM qa
GROUP BY IFNULL(parent_id, 0)
Can you post actual data and full query which exhibits the behavior you are talking about? In my experience, COUNT(*) can never be NULL.
Can Count(*) ever return null?
Does COUNT(*) always return a result?
Related
i could not find the correct query of sql, how i can use if else statement in sum?? i want add sum(if(noresult),0,number) if there is no any result. but it doesnt work.
INNER JOIN ( SELECT
COUNT(*), SUM(cekilen_tutar) AS bal_total
FROM alinanbaliklar
WHERE user_id = 1
GROUP BY user_id )balik
INNER JOIN ( SELECT
COUNT(*), SUM(cekilen_tutar) AS dom_total
FROM alinandomuzlar
WHERE user_id = 1
GROUP BY user_id )domuz
INNER JOIN ( SELECT
COUNT(*),SUM(cekilen_tutar) AS seb_total
FROM alinanmeyvesebzeler
WHERE user_id = 1
GROUP BY user_id )sebze
INNER JOIN ( SELECT
COUNT(*), SUM(cekilen_tutar) AS ag_total
FROM alinanagaclar
WHERE user_id = 1
GROUP BY user_id )agac
You are only selecting one row. So, dispense with the GROUP BY and use CROSS JOIN:
FROM (SELECT COUNT(*), SUM(cekilen_tutar) AS bal_total
FROM alinanbaliklar
WHERE user_id = 1
) balik CROSS JOIN
(SELECT COUNT(*), SUM(cekilen_tutar) AS dom_total
FROM alinandomuzlar
WHERE user_id = 1
) domuz CROSS JOIN
(SELECT COUNT(*), SUM(cekilen_tutar) AS seb_total
FROM alinanmeyvesebzeler
WHERE user_id = 1
) sebze CROSS JOIN
(SELECT COUNT(*), SUM(cekilen_tutar) AS ag_total
FROM alinanagaclar
WHERE user_id = 1
) agac
I have a query with WHERE EXISTS and DISTINCT. I just want to find distinct emails with same order_id
How can I make this faster
select DISTINCT(user_email)
from (
SELECT *
FROM orders mto
WHERE EXISTS
(
SELECT 1
FROM orders mti
WHERE mti.order_id = mto.order_id
LIMIT 1, 1
)
) as z
INNER JOIN marketplaces as u ON z.ump_id = u.id
You are doing excess/needless work - the EXISTS will always return TRUE in your situation.
If you want a list of all (unique) emails which have at least 1 order, then
SELECT
user_email
FROM
marketplaces
LEFT JOIN
orders ON ump_id = marketplaces.id
WHERE orders.id IS NOT NULL
GROUP BY user_email
If you want to get a list with all (unique) emails for a given order ID, then
SELECT
user_email
FROM
orders
LEFT JOIN
orders ON ump_id = marketplaces.id
WHERE orders.id = 17
GROUP BY user_email
In my MySQL database I have these tables:
I want to select count of users who only own birds and no other pet.
So far I've came up with this:
SELECT COUNT(DISTINCT(user_id)) FROM users_pets_map WHERE pet_id IN (SELECT id FROM pets WHERE animal = 'bird')
but it doesn't satisfy the requirement of not owning other animals.
You can do aggregation :
select m.user_id, count(*)
from user_pets_map m inner join
pets p
on p.id = m.pet_id
group by m.user_id
having sum( p.animal <> 'bird' ) = 0;
In other way, you can also do :
select m.user_id, count(*)
from user_pets_map m inner join
pets p
on p.id = m.pet_id
group by m.user_id
having min(p.animal) = max(p.animal) and min(p.animal) = 'bird';
EDIT : If you want only Users count then you can do :
select count(distinct m.user_id)
from user_pets_map m
where not exists (select 1 from user_pets_map m1 where m1.user_id = m.user_id and m1.pet_id <> 3);
You can modify your query as below:
SELECT COUNT(DISTINCT(user_id)) FROM users_pets_map WHERE pet_id IN (SELECT id
FROM pets WHERE animal = 'bird') AND user_id NOT IN (SELECT user_id FROM
users_pets_map WHERE pet_id IN (SELECT id FROM pets WHERE animal <> 'bird'))
The last sub-query will fetch the pet_id who are not birds, the query outside it will fetch users who have animal other than birds. Finally combined your current query it will fetch you the users who does not have any other animals as well as have bird. Although the above query is not the best possible solution in terms of time complexity, but it's one of many solutions as well as easier to understand.
You can use GROUP BY AND HAVING
SELECT COUNT(DISTINCT(user_id)) FROM users_pets_map
WHERE pet_id IN (SELECT id FROM pets WHERE animal = 'bird')
GROUP BY pet_id HAVING COUNT(distinct pet_id)=1
I'm trying to insert the value '1' into column 'isTransfer' of every result of an subquery, but it's not working. This is the query where I select the rows:
select r.*
from players r
inner join (
select name, rating, max(id) id
from players group by name, rating
having count(distinct club) > 1
)
q on r.name = q.name and r.rating = q.rating and r.id = q.id
This is what I'm trying to do:
INSERT INTO 'isTransfer' VALUES '1' WHERE
(select r.*
from players r
inner join (
select name, rating, max(id) id
from players group by name, rating
having count(distinct club) > 1
)
q on r.name = q.name and r.rating = q.rating and r.id = q.id)
For this task, you need to do an UPDATE query. Also, you cannot use the WHERE clause like that, you will get an error. Instead, change the where clause to look where the primary key is returned by the subquery. It would look something like this:
UPDATE myTable
SET isTransfer = 1
WHERE primaryKey IN [mySubquery];
You need to make sure that the only column in your SELECT of the subquery is the primary key, otherwise you will get an invalid operand count error.
In regards to your query in the comments, the JOIN is not necessary. Instead, just get the distinct id values from the subquery like this:
SELECT DISTINCT id
FROM(
SELECT name, rating, MAX(id) AS id
FROM players
GROUP BY name, rating
HAVING COUNT(DISTINCT club) > 1) q
Then, but that query as your IN operand.
Assuming the id is unique in the players table:
update players r inner join
(select name, rating, max(id) as id
from players p
group by name, rating
having count(distinct club) > 1
) nr
on r.id = nr.id
set isTransfer = 1;
I don't actually need the following query, but I woke up with this "theoretical problem" that I'm having trouble figuring out. Say I have three tables: a users table, groups table, and users_groups table that is a many-to-many. So if one user belongs to group 1 and 2, there would be two different rows for each.
Now, assuming that there are many groups, how do I select specifically the users that belong to both group 2 and 3, for example?
I tried something along these lines, but it showed empty:
SELECT * FROM `users_groups` GROUP BY user_id HAVING group_id = 2 AND group_id = 3
I guess that assumes that both groups are in the same row, which obviously won't work. How would I do this?
EDIT: How about both variants: where the user must ONLY be in these two groups, and the user must AT LEAST be in these two groups?
SELECT *
FROM users_groups
GROUP BY user_id
WHERE group_id IN (2,3)
HAVING COUNT(1) = 2
This of course assumes that {user_id, group_id} is unique (and there are no other columns there to add additional rows to the count). Otherwise you could ensure this explicitly:
SELECT *
FROM users_groups
GROUP BY user_id
WHERE group_id IN (2,3)
HAVING COUNT(DISTINCT group_id) = 2
Only in these two groups is slightly more complicated. You can either do:
SELECT *
FROM users_groups g1
GROUP BY user_id
WHERE group_id IN (2,3)
AND NOT EXISTS
(
SELECT 1
FROM users_groups AS g2
WHERE g2.user_id = g1.user_id
AND group_id NOT IN (2,3)
)
HAVING COUNT(1) = 2
Or,
SELECT *
FROM users_groups g1
GROUP BY user_id
HAVING COUNT(1) = 2
AND SUM(CASE WHEN group_id IN (2,3) THEN 1 ELSE 0 END) = 2
In groups 2 and 3, with more than 2 groups total:
SELECT *
FROM users_groups g1
GROUP BY user_id
HAVING SUM(CASE WHEN group_id IN (2,3) THEN 1 ELSE 0 END) = 2
AND COUNT(1) > 2
The problem is called Relational Division.
SELECT a.ID, a.Name
FROM users a
INNER JOIN users_groups b
ON a.ID = b.UserID
INNER JOIN groups c
ON b.group_ID = c.ID
WHERE c.Name IN ('grp2', 'grp3')
GROUP BY a.ID, a.Name
HAVING COUNT(DISTINCT c.Name) = 2
DISTINCT was used in the following query if a unique constraint on Name isn't enforce for every user, otherwise HAVING COUNT(*) = 2 will suffice.
SQL of Relational Division
SELECT *, COUNT(*) FROM `users_groups`
WHERE group_id IN (2,3)
GROUP BY user_id HAVING COUNT(*) > 1
User must ONLY belong to grp 2 and grp 3:
SELECT *, group_concat(group_id ASC) gui
FROM users_groups
GROUP BY user_id
HAVING gui="2,3"
SELECT user_id
FROM (select * from users_groups where group_id = 2) grp 1, (select * from users_groups where group_id = 3) grp2
where grp1.user_id = grp2.user_id