Listing both null and not null in mysql query - mysql

Let's say I have the table
NAME | ID | REF
foo1 | 1 | NULL
foo2 | 2 | 1234
foo2 | 3 | 567
foo1 | 4 | NULL
foo3 | 5 | 89
I'd like to count all instances of NULL and NOT NULL in one query so that I can say
NAME | null | not null
foo1 | 0 | 2
foo2 | 2 | 0
foo3 | 0 | 1
I could run these two queries
select NAME,count(*) from TABLE where REF is not null
select NAME,count(*) from TABLE where REF is null
But I'm sure there must be a simple way to do it in one mysql query.

You can use SUM() on ISNULL() like this
select NAME, sum(isnull(REF)) as is_null, sum(not isnull(REF)) as is_not_null from TABLE group by NAME;
SUM(1) is equivalent to COUNT(*), so it will really make a count.

If it is ok with a solution that uses grouping you can try something like:
SELECT ISNULL(ref),COUNT(*) FROM TABLE GROUP BY ISNULL(ref)
At least it tells you how many row with a NULL in ref you have.
This solution (good or not) could be extended with a select of GROUP_CONCAT on NAME if you need to select every individual name.

I think MySQL has an IF() function, so you could write:
SELECT Name, SUM(IF(ISNULL(Ref), 1, 0)) AS NullCount,
SUM(IF(ISNULL(Ref), 0, 1)) AS NotNullCount
FROM Table GROUP BY Name
So, you're using the IF() function to generate either a zero or a one for each row, and summing them to get the total number of "ones".

Related

How to select both sum value of all rows and values in some specific rows?

I have a record table and its comment table, like:
| commentId | relatedRecordId | isRead |
|-----------+-----------------+--------|
| 1 | 1 | TRUE |
| 2 | 1 | FALSE |
| 3 | 1 | FALSE |
Now I want to select newCommentCount and allCommentCount as a server response to the browser. Is there any way to select these two fields in one SQL?
I've tried this:
SELECT `isRead`, count(*) AS cnt FROM comment WHERE relatedRecordId=1 GROUP BY `isRead`
| isRead | cnt |
| FALSE | 2 |
| TRUE | 1 |
But, I have to use a special data structure to map it and sum the cnt fields in two rows to get allCommentCount by using an upper-layer programming language. I want to know if I could get the following format of data by SQL only and in one step:
| newCommentCount | allCommentCount |
|-----------------+-----------------|
| 2 | 3 |
I don't even know how to describe the question. So I got no any search result in Google and Stackoverflow. (Because of My poor English, maybe)
Use conditional aggregation:
SELECT SUM(NOT isRead) AS newCommentCount, COUNT(*) AS allCommentCount
FROM comment
WHERE relatedRecordId = 1;
if I under stand you want show sum of newComments Count and all comments so you can do it like
SELECT SUM ( CASE WHEN isRead=false THEN 1 ELSE 0 END ) AS newComment,
Count(*) AS AllComments From comments where relatedRecord=1
also you can make store procedure for it.
To place two result sets horizontally, you can as simple as use a subquery for an expression in the SELECT CLAUSE as long as the number of rows from the result sets match:
select (select count(*) from c_table where isread=false and relatedRecordId=1 ) as newCommentCount,
count(*) as allCommentCount
from c_table where relatedRecordId=1;

SQL Use Result from one Query for another Query

This is an excerpt from one table:
| id | type | other_id | def_id | ref_def_id|
| 1 | int | NULL | 5 | NULL |
| 2 | string | NULL | 5 | NULL |
| 3 | int | NULL | 5 | NULL |
| 20 | ref | 3 | NULL | 5 |
| 21 | ref | 4 | NULL | 5 |
| 22 | ref | 5 | NULL | 5 |
What I want is to find entries with type ref. Then I would for example have this one entry in my result:
| 22 | ref | 5 | NULL | 5 |
The problem I am facing is that I now want to combine this entry with other entries of the same table where def_id = 5.
So I would get all entries with def_id = 5 for this specific ref type as result. I somehow need the output from my first query, check what the ref_def_id is and then make another query for this id.
I really have problems to understand how to proceed. Any input is much appreciated.
If I understand correctly you need to find rows with a type of 'ref' and then use the values in their ref_def_id columns to get the rows with the same values in def_id. In that case you need to use a subquery for getting the rows with 'ref' type and combine it using either IN or EXISTS:
select *
from YourTable
where def_id in (select ref_def_id from YourTable where type='ref');
select *
from YourTable
where exists (select * from YourTable yt
where yt.ref_def_id=YourTable.def_id and yt.type='ref')
Both queries are equivalent, IN is easier to understand at first sight but EXISTS allow more complex conditions (for example you can use more than one column for combining with the subquery).
Edit: since you comment that you need also the id from the 'ref' rows then you need to use a subquery:
select source_id, YourTable.*
from YourTable
join (select id as source_id, ref_def_id
from YourTable
where type='ref')
as refs on refs.ref_def_id=YourTable.def_id
order by source_id, id;
With this for each 'ref' row you would get all the rows with the associated ref_id.
use below query to get column from sub query.
select a.ref_def_id
from (select ref_def_id from YourTable where type='ref') as a;
What you are looking for is a subquery or even better a join operation.
Have a look here: http://www.mysqltutorial.org/mysql-left-join.aspx
Joins / the left join allows you to combine rows of tables within one query on a given condition. The condition could be id = 5 for your purpose.
You would seem to want aggregation:
select max(id) as id, type, max(other_id) as other_id,
max(def_id) as def_id, ref_def_id
from t
where type = 'ref'
group by type, ref_def_id

Select different column in a row depending on the value

I am trying to return a friend list for my users and I'm trying to gather the value matching their user_id.
| ID | user1_id | user1_status | user2_id | user2_status |
| 1 | 1 | 0 | 2 | 0 |
| 2 | 4 | 1 | 5 | 1 |
| 3 | 4 | 1 | 6 | 0 |
| 4 | 1 | 0 | 4 | 1 |
Here is the problem I have, the value I'm look for can be in either "user1_id"/"user2_id" and then I need to return the "user_status" ONLY for the other user. n. I made this table really simple. In my version there is a lot more columns I want my server to avoid returning.
Let's say that the client user_id is 4, so I need the select all the row with user1_id/user2_id equal to 4 and return the other person user_status. In the table, the first case of the value equal to 4 is in user1_id, I need that row to return the user2_id and user2_status.
Here is what I have so far, but it doesn't work:
SELECT `id`
CASE
WHEN `user1_id`='4' THEN `user2_id` AND `user2_status`
WHEN `user2_id`='4' THEN `user1_id` AND `user1_status`
ELSE NULL
END
from 'relationship'
where `user1_id`='4' OR `user2_id`='4'
How do I write this query statement?
If you refer to the CASE syntax you will see that it's defined to return a single column and not a tuple. Additionally, in your query you are trying to get either (user2_id, user_status) or NULL. Here you get a mismatch in the number of columns which is not allowed either.
If you really really want to use CASE you could do:
SELECT `id`
CASE
WHEN `user1_id`='4' THEN `user2_id`,
ELSE NULL
END
CASE
WHEN `user2_id`='4' THEN `user1_id`
ELSE NULL
END
CASE
WHEN `user1_id`='4' THEN `user1_status`
ELSE NULL
END
CASE
WHEN `user2_id`='4' THEN `user2_status`
ELSE NULL
END
FROM 'relationship'
where `user1_id`='4' OR `user2_id`='4'
yes, clunky and confusing. Much Simpler if you use UNION.
SELECT id, user2_id AS uid, user2_status as ustatus FROM relationship WHERE user1_id = 4
UNION
SELECT id, user1_id AS uid, user1_status as ustatus FROM relationship WHERE user2_id = 4

filter sql rows using update statement

I am trying to write a query which can get invalid refby(is related to id), please check following db structure...
| id | acnumber | refby |
+----+-----------+--------+
| 1 | ac01 | 2 |
+----+-----------+--------+
| 2 | ac02 | 1 |
+----+-----------+--------+
| 3 | ac03 | 5 |
+----+-----------+--------+
As you can find there is no id with value of 5 in above table so query must return 3rd row as result.
I have tried...
SELECT * FROM tbl.members WHERE refby != (SELECT id FROM tbl.members WHERE id = refby)
But this is not giving correct results, please help, thanks.
SELECT * FROM members WHERE refby not in (SELECT id FROM members)
This should solve your problem
You can try this using not in:-
SELECT * FROM tbl.members WHERE refby not in (SELECT id FROM members)
This should be a LEFT JOIN, NOT IN is slow on large tables... assuming id and refid is an PRIMARY KEY or UNIQUE key (read unique within your dataset) then this query should return the same results.
SELECT
*
FROM
members members1
LEFT JOIN
members members2
ON members1.id = members2.refby
WHERE members2.id IS NULL
check the sqlfriddle http://sqlfiddle.com/#!2/05731/1

Mysql select IN return null if id not exists

I have a table like this:
+----+---------+---------+
| Id | column1 | column2 |
+----+---------+---------+
| 1 | a | b |
| 2 | a | b |
+----+---------+---------+
and a query like this SELECT * FROM table WHERE id IN (1,2,3)
what query do I need to get a result like this(I need to get null values for nonexisten id's):
+----+---------+---------+
| Id | column1 | column2 |
+----+---------+---------+
| 1 | a | b |
| 2 | a | b |
| 3 | null | null |
+----+---------+---------+
EDIT
Thanks for the responses so far.
Is there a more 'dynamic way' to do this, the query above it's just an example.
In reality I need to check around 1000 id's!
You could use something like this:
SELECT ids.ID, your_table.column1, your_table.column2
FROM
(SELECT 1 as ID
UNION ALL SELECT 2
UNION ALL SELECT 3) ids left join your_table
on ids.ID = your_table.ID
First subquery returns each value you need in a different row. Then you can try to join each row with your_table. If you use a left join, all values from the first subquery are shown, and if there's a match with your_table, values from your_table are shown, otherwise you will get nulls.
That is not the way SQL works unfortunately. I would think it would be pretty trivial for your application to determine the differences between the id's it asked for and the id's returned.
So rather than hack or some weird query to mock up your result, why not have your application handle it?
I still can't understand though what the use case might be to where you would be querying rows on teh database by id's that may or may not exist.