Ignore row if returns null sql - mysql

I am using Alias.
Below is my query. I want to avoid showing rows with NULL counter.
SELECT activity_id, user_id,
(CASE WHEN activity_id = 1 OR activity_id = 2 THEN user_id END) AS counter
FROM eventedge_ticket_activity
It gives the following result:
How can I skip rows with counter NULL?

Not tested, but below should work.
SELECT activity_id, user_id,
CASE activity_id WHEN 1 THEN user_id
WHEN 2 THEN user_id
ELSE NULL
END AS counter
FROM eventedge_ticket_activity
WHERE counter IS NOT NULL

Below is the query which ran successfully.
SELECT * FROM (SELECT activity_id, user_id, case when activity_id=1 then user_id when activity_id=2 then user_id end as counter FROM eventedge_ticket_activity) db where counter != 'NULL'

I have a feeling that the sample data is over simplified so I may be quite wrong but this looks like the same query parsing the data only once.
SELECT activity_id, user_id,
user_id AS counter
FROM eventedge_ticket_activity
WHERE activity_id in(1,2)
BTW the answer provided by marmeladze should also work with the change I mentioned in my comment

Inner 'SELECT' gives table with NULL's, outer 'SELECT' cuts off rows with NULL counter
SELECT * FROM (
SELECT activity_id, user_id,
(CASE WHEN activity_id = 1 OR activity_id = 2 THEN user_id END) AS counter
FROM eventedge_ticket_activity) AS ResultTable
WHERE ResultTable.counter IS NOT NULL

Related

Selecting distinct count in a group with only null values for a specific column

I have 2 columns like this - id and val.
I require such distinct id's where corresponding to each id there is a null value present.
Is it plausible to use "group by" by id and then use "having" clause where null is there?
I would use NOT EXISTS :
SELECT COUNT(DISTINCT id)
FROM table t
WHERE NOT EXISTS (SELECT 1 FROM table t1 WHERE t1.id = t.id AND t1.val IS NOT NULL);
Other option uses the GROUP BY :
SELECT COUNT(id)
FROM table t
GROUP BY id
HAVING SUM(CASE WHEN val IS NOT NULL THEN 1 ELSE 0 END) = 0;
To get ids that have a NULL value, I would be inclined to start with this:
select id
from t
group by id
having count(*) <> count(val);
This structure allows you to check for other values, such as a non-NULL value.
The simplest method to get the distinct ids with NULL values is:
select distinct id
from t
where val is null;
If you only want the count:
select count(distinct id)
from t
where val is null;

Insert empty row after group

I have a table that contains transaction data. The rows with the same 'group_id' are a part of the same transaction. I am running the following SQL query to show all the transactions:
SELECT * FROM transactions
When I run this query I get as expected a list of all the transactions. But this large list makes it difficult to seperate the data with a different group_id from the other data.
For that reason I want to add an empty row at the end of the group_id, so I get:
1
1
(empty row)
2
2
2
instead of:
1
1
2
2
2
Can someone help me with this?
Here is my database:
http://sqlfiddle.com/#!9/b9bf79/1
I do not suggest you do this at all but if you just want to separate two groups you could do this:
SELECT * FROM transactions WHERE group_id = 1
UNION ALL
(SELECT '','','','','','')
UNION ALL
SELECT * FROM transactions WHERE group_id = 2
Obviously this can added to if there are more group ids in the future but it is not a general purpose solution you are really better off dealing with appearance issues like this in application code.
you can use (abuse) rollup.
SELECT *
FROM transactions
group by group_id, id
with rollup
having group_id is not null
this will insert a row with id set to null after each group_id.
mysql will also sort by group_id because of the group by.
The group by id` makes sure that all rows are shown (your schema does not show it, but I assume id is unique? Otherwise you need to add other fields)
However only id will be null in the extra rows. The other columns repeat the value above.
You can filter them like this:
SELECT
id,
case id is not null when true then date else null end as date,
case id is not null when true then group_id else null end as group_id
-- ....
FROM transactions
group by group_id, id
with rollup
having group_id is not null
Alternatively:
select * from
(SELECT *
FROM transactions
union all
select distinct null, null, group_id, null, null,null from transactions
) as t
order by 3,1
but null values are sorted first, so the "gap" is in front of each section

Get latest value of field using group by

I am making a query in which i want the job ids to be grouped but i want the latest timestamp row in the result which is not happening
Here is the SQL fiddle
http://sqlfiddle.com/#!9/de8769
The normal view for table is
The output after using this query i made
SELECT
DISTINCT(user_id),
job_id,
message,
receiver_id,
parent,
type,
id as id FROM ai_ms_messages
WHERE (receiver_id = '7' OR user_id = '7') AND type<>0 AND type<>2 group by job_id
ORDER BY max(timestamp) DESC
But as you can see its taking the value of id as 3 for job_id 11 but it should have taken the value 5 (as that is latest for job_id 11) and also the order is wrong. Since job_id 11 is latest not job_id 12. Is there any way to achieve this ?
The query would be:
select
distinct(m1.user_id),
m1.job_id,
m1.message,
m1.receiver_id,
m1.parent,
m1.type,
m1.id as id from ai_ms_messages as m1
where m1.type<>0 and m1.type<>2
and m1.timestampt = (select max(m2.timestamp) from ai_ms_messages as m2 where m2.job_id = m1.job_id)
As per your query you are looking for data for receiver_id = '7' and for id =5 , receiver_id = '6' , so this is not in your query output.
Just remove where condition, or check data as per condition only.
GROUP BY groups on the first matching result it hits.
So, its preferable this method as the subquery.
SELECT *
FROM (
SELECT DISTINCT (
user_id
), job_id, message, receiver_id, parent,
TYPE , id AS id
FROM ai_ms_messages
WHERE (
receiver_id = '7'
OR user_id = '7'
)
AND TYPE <>0
AND TYPE <>2
ORDER BY TIMESTAMP DESC
) AS sub
GROUP BY job_id

How to bypass a reference to an outer table in subquery?

I've been dealing with these two tables:
Document
id company_id etc
=======================
1 2 x
2 2 x
Version
id document_id version date_created date_issued date_accepted
==========================================================================
1 1 1 2013-04-29 2013-04-30 NULL
2 2 1 2013-05-01 NULL NULL
3 1 2 2013-05-01 2013-05-01 2013-05-03
There's a page where I want to list all documents with their attributes.
And I would like to add a single have status from each document.
The status can be derived from the most present date that corresponding Versions have.
It is possible that an older version is being accepted.
The query result I am looking for is like this:
id company_id etc status
==================================
1 2 x accepted
2 2 x created
I started out by making a query which combines all dates and add a status next to it.
It works as expected and when I add the document_id things look alright.
SELECT `status`
FROM (
SELECT max(date_created) as `date`,'created' as `status` FROM version WHERE document_id = 1
UNION
SELECT max(date_issued),'issued' FROM version WHERE document_id = 1
UNION
SELECT max(date_accepted),'accepted' FROM version WHERE document_id = 1
ORDER BY date DESC
LIMIT 1
) as maxi
When I try to incorporate this query as a subquery, I can't make it work.
SELECT *, (
SELECT `status` FROM (
SELECT max(date_created) as `date`,'created' as `status`FROM version WHERE document_id = document.id
UNION
SELECT max(date_issued),'issued' FROM version WHERE document_id = document.id
UNION
SELECT max(date_accepted),'accepted' FROM version WHERE document_id = document.id
ORDER BY date DESC
LIMIT 1
) as maxi
) as `status`
FROM `document`
This will get me the error Unknown column 'document.id' in 'where clause'. So I've read around at SO and figured it simply can't reach the value offer.id since it's a subquery in a subquery. So I tried to take another approach and get all the statuses at once, to avoid the WHERE statement, and JOIN them. I ended up with the next query.
SELECT MAX(`date`),`status`, document_id
FROM (
SELECT datetime_created as `date`, 'created' as `status`,document_id FROM `version`
UNION
SELECT datetime_issued, 'issued',document_id FROM `version`
UNION
SELECT datetime_accepted, 'accepted',document_id FROM `version`
) as dates
GROUP BY offer_id
No error this time but I realized that the status couldn't be the correct one since it got lost during the GROUP BY. I've tried combinations of the two but both flaws keep hindering me. Could any one suggest how to do this in a single query without changing my database? (I know that saving the dates in a separate table would simply things)
I have not tested this, but you can do it like this (you might need to tweak the details)
It is basically looking at it from a completely different angle.
select
d.*,
(CASE GREATEST(ifnull(v.date_created, 0), ifnull(v.date_issued,0), ifnull(v.date_accepted,0) )
WHEN null THEN 'unknown'
WHEN v.date_accepted THEN 'accepted'
WHEN v.date_issued THEN 'issued'
WHEN v.date_created THEN 'created'
END) as status
from document d
left join version v on
v.document_id = d.document_id and
not exists (select 1 from (select * from version) x where x.document_id = v.document_id and x.id <> v.id and x.version > v.version)
Can you normalise your table designs to move the status / dates onto a different table from the Versions?
If no possibly something like this:-
SELECT Document.id, Document.company_id, Document.etc, CASE WHEN Sub1.status = 3 THEN 'accepted' WHEN Sub1.status = 2 THEN 'issued' WHEN Sub1.status = 1 THEN 'created' ELSE NULL END AS status
FROM Document
INNER JOIN (
SELECT document_id, MAX(CASE WHEN date_accepted IS NOT NULL THEN 3 WHEN date_issued IS NOT NULL THEN 2 WHEN date_created IS NOT NULL THEN 1 ELSE NULL END) AS status
FROM Version
GROUP BY document_id
) Sub1
ON Document.id = Sub1.document_id
The subselect gets the highest status for any document from the version table. Each possible versions highest status is returned as a number, and by grouping that on the document id it will get the highest status of any version. This is joined back against the Document table and the number for the version number converted into the text description.
select Doc.document_id,Doc.company_id,Doc.etc,f.status
from Document Doc
inner join
(select Ver.document_id,
case when Ver.date_accepted is not null then 'Accepted'
when Ver.date_issued is not null then 'Issued'
when Ver.date_created is not null then 'Created'
end as status
from version Ver
inner join (
select document_id,MAX(version) VersionId
from version
group by document_id
)t on t.document_id=Ver.document_id
where t.VersionId=Ver.version
)f on Doc.document_id=f.document_id
SQL Fiddle

mySQL order by count subquery trouble

I have a table called items_status which has 3 fields, item_id, user_id, and status, which can be either 'have' or 'want'.
Field Type Null Key
user_id varchar(10) NO PRI
item_id varchar(10) NO PRI
status set('have','want') YES NULL
I have a page where I want to get a list of all the user ids in the table ordered by the number of records their user id is associated with in the table where status is 'have'. So far, this is the best I can come up with:
SELECT user_id
FROM items_status AS is
ORDER BY
//Subquery to get number of items had by user
(SELECT COUNT(i.item_id)
FROM items_status AS i
WHERE i.user_id = is.user_id AND i.status = 'have') DESC
GROUP BY user_id
However, this pulls up an error on the subquery. How can I get all of the user ids in the table ordered by the number of items they have?
you can do it like this:
SELECT user_id
FROM items_status
WHERE `status` = 'have'
GROUP BY userID
ORDER BY COUNT(user_id) DESC
SQLFiddle Demo
with slight difference of column name but the query is the same
SELECT user_id, SUM(CASE WHEN i.status = 'have' THEN 1 ELSE 0) AS s
FROM items_status AS is
GROUP BY user_id
ORDER BY SUM(CASE WHEN i.status = 'have' THEN 1 ELSE 0) DESC