I've looked all over the site for counting the number of times a value occurs in a query and found answers but nothing addressing it in a case statement.
here is the query I am using that returns results but the results should be higher...the results are in the 70's but should be double that number.
query:
select count(case when field#1 like "Y" then "1" else null end) as column name
from db
where datefield like '2015-04%'
To accomplish something like this, it's more helpful to use conditional aggregation.
This means, instead of using a case statement to sum items, you just put the condition in the SUM() function:
SELECT SUM(field1 LIKE '%y%')'
...
If you don't want to use the conditional aggregation approach, and prefer to use CASE, you'll need to use SUM() instead of COUNT() like this:
SELECT SUM(CASE WHEN field1 LIKE '%y%' THEN 1 ELSE 0 END) AS counts
...
Related
I am learning SQL now and I am kind of confused when encountering a query like this:
SELECT CASE
WHEN url like '%abc.com%'THEN 'abc'
When url like '%def.com%'THEN 'def'
When url like '%smiley.com%' THEN 'Smiley'
Else 'others'
End AS 'sites', count(*)
FROM websites_sources
GROUP BY 1;
The query above works correctly, but only if the GROUP BY Statement uses 1. If I write Group BY 'sites', the result only shows 'others' and the total count of ALL rows (instead of the count for 'others' only and other sites).
My question is, so for GROUP BY Statement we can only use number to indicate grouping, and not the name of the column?
Thanks for your help!
Only use single quote for string and date constants. Never use single quotes for column aliases. You'll just confuse yourself.
Try this:
SELECT (CASE WHEN url like '%abc.com%' THEN 'abc'
WHEN url like '%def.com%' THEN 'def'
WHEN url like '%smiley.com%' THEN 'Smiley'
ELSE 'others'
END) AS sites,
count(*)
FROM websites_sources
GROUP BY sites;
You are grouping by the string 'sites', which is a constant, not the column named sites.
Say I have a table that has the transactions of a store.
How can I count the number of transactions that have the word "crackers" in it, the number of transactions that have "soda" in it, and the number of transactions that have both "crackers" and "soda" in it.
If possible, this should be in a single query.
You can use conditional aggregation for this:
select
sum(case when field like '%crackers%' then 1 else 0 end) crackercount,
sum(case when field like '%soda%' then 1 else 0 end) sodacount,
sum(case when field like '%soda%'
and field like '%crackers%' then 1 else 0 end) bothcount
from yourtable
SQL Fiddle Demo
In Postgres 9.4 or later, use the dedicated aggregate FILTER clause:
SELECT count(*) FILTER (WHERE col ILIKE '%crackers%') AS ct_cracker
, count(*) FILTER (WHERE col ILIKE '%soda%') AS ct_soda
, count(*) FILTER (WHERE col ILIKE ALL ('{%crackers%, %soda%}'::text[]) AS ct_both
FROM tbl
WHERE col ILIKE ANY ('{%crackers%, %soda%}'::text[]);
There are a couple of standard techniques that work for older versions or MySQL, too:
For absolute performance, is SUM faster or COUNT?
Assuming you want case-insensitive pattern matching, hence ILIKE.
The ANY and ALL constructs are handy features, especially for longer arrays, but not strictly necessary for your problem. Also, the WHERE clause is not strictly needed, but typically improves performance.
Details:
How can I simplify this game statistics query?
I am sure it would be an aggregate function because it is going to count a collection of data.
However, how does any COUNT() function operate in MySQL to perform its respective actions?
Not 100% clear what you are looking for, but for selecting a count of null values in a column, I use something like this:
SELECT SUM(CASE WHEN columnname IS NULL THEN 1 ELSE 0 END) FROM tablename;
When the value is NULL, it is assigned the value 1 otherwise 0, then summed over whatever aggregate you need.
The COUNT(*) is an aggregate function. In the SELECT list, the expression COUNT(*) will return a count of rows. Without a GROUP BY clause, all rows will be collapsed into a single row, and the COUNT(*) aggregate will contain a non-negative integer value representing the number of rows that were collapsed... a "count" of the number of rows.
As you seem to be aware, other expressions involving the COUNT() aggregate operate a little differently, with respect to NULL values.
In the SELECT list, an expression COUNT(expr) operates exactly like COUNT(*) except for rows with values of expr that evaluate to NULL are not included in the count.
This all operates according to the specification.
As far as the non-existent COUNTNULL() function, it depends what you want that to achieve. If you wanted to get a count of the rows that had a NULL value for an expression, you could perform a conditional test, and return a non-NULL value, and use the existing COUNT aggregate, for example:
SELECT COUNT(CASE WHEN expr IS NULL THEN 1 ELSE NULL END) AS `COUNTNULL`
FROM ...
I don't remember where I learned this technique, but arguably the most elegant -- or at least minimalistic -- way to invert the logic of COUNT() is with this expression, which admittedly gives a first impression that black magic may somehow be involved... but it's perfectly legitimate:
COUNT(column1 IS NULL OR NULL)
...this correctly counts only the rows where column1 is null, because it is equivalent to the following expression...
COUNT( (column1 IS NULL) OR (NULL) )
It's a boolean expression that can only ever evaluate to 1 ("true," when column1 is null, and this row is thus counted), or NULL (otherwise, so the row will not be counted).
Logically, it's equivalent to the CASE expression offered by #spencer7593.
I was surprised to see one of my students writing
select count(title='Staff') from titles
against MySQL employees database. Does it mean to be a nice shortcut for
select sum(case when title='Staff' then 1 else 0 end) from titles
which just fails to work in MySQL 5.6 (returning full table count)?
No, this count is not a shorthand for the sum you wrote.
COUNT(exp) counts the number of rows with a not null exp.
title='Staff' is a Boolean expression, which evaluates to true if title is 'Staff', false if it's any other value or null if it's null.
So, this query is equivalent to
select count(title) from titles
which, in turn, is equivalent to
select count(*) from titles where title is not null
No!
You can't count against an condition write into brackets. It simple return all rows from that table.
select count(title='Staff') from titles
return all rows from titles
is it possible to get the average value for a column, as well as the average value for the same column with a conditional? or simply to combine these two queries into one.
SELECT AVG( field ) from table
SELECT AVG ( field ) from table where col = some_val
If there isn't a simple way to combine them using native mysql functions, would a stored function be able to handle it, or a user defined function?
Taking advantage of the fact that null values are not included in aggregate functions, we can use a CASE statement to control the average, as in the following:
select avg(amt) as average,
avg(case when col=some_val then amt else null end) as conditionalAverage
from myTable;
Sample Demo: http://sqlize.com/2IXwbWD2Eb
There is another way, not using case when
select
avg(amt) as average,
avg(if(col=some_val,amt,null)) as conditionalAverage
from myTable