Mysql query on a single table - mysql

I have a transaction table with datetime, type, measure. I want to produce the day, count, count with measure>20 for type=12.
Not sure how to go about it.
To get the day, count, type I'd write
select date(datetime), count from table where type=12 group by date(datetime)
Just not sure how to add the 3rd col (count with measure>20).
I've thought of trying a left self join, or a corelated subquery.
Appreciate any advice.
Table Name Alerts
Col1 Alert_time (datetime)
Col 2 Alert_type (integer)
Col 3 Measure (integer)
Sample data
2015/01/20 9:00|12|10
2015/01/20 8:00|12|30
2015/01/20 7:00|12|40
2015/01/21 5:00|13|30
2015/01/21 8:00|12|10
Desired Output
2015/01/20|3|2
2015/01/21|1|0

You could perform a count operation on a case expression:
SELECT DATE(datetime),
COUNT(*),
COUNT(CASE WHEN measure > 20 THEN 1 ELSE NULL END)
FROM mytable
WHERE type = 12
GROUP BY date(datetime)

You can have you query like this.
SELECT DATE(datetime),
COUNT(*),
COUNT(CASE WHEN measure > 20 THEN 1 ELSE 0 END)
FROM mytable
WHERE type = 12
GROUP BY date(datetime)

Related

Add a column from subquery to the SELECT of main query without applying filteres from WHERE in main query

I need a help with following problem:
So I have a table TABLE1 with columns Date, Name, STAT1, STAT2, PROBLEM1
I have a query like this:
SELECT Date, Name, sum(STAT1), sum(STAT2)
FROM TABLE1
WHERE PROBLEM1 <> 0
GROUP BY Date, Name
The result of this query is what I want but I also need to add 2 columns: TOTALCOUNT which is basically the number of rows for each group without applying the filter (PROBLEM1 <> 0 ) and COUNTERRORS which is count for each group where PROBLEM1 = 0.
So to give you further example. For a Date A, and Name B I have 1000 rows. 300 of them have PROBLEM1 = 0.
I run the first query I mentioned above and it calculates my sum(STAT1), sum(STAT2) based on 700 rows because of the filter WHERE PROBLEM1 <> 0. And I need to find a way to add two columns to the result so in the end my table would look like:
DATE NAME sum(STAT1) sum(STAT2) TOTALCOUNT COUNTERRORS
A B 50 3.5 1000 300
Is it possible to do? I was trying using subqueries but without a success.
You can do conditional aggregation :
SELECT Date, Name,
sum(case when PROBLEM1 <> 0 then stat1 else 0 end) as stat1,
sum(case when PROBLEM1 <> 0 then stat2 else 0 end) as stat2,
count(*) as TOTALCOUNT,
sum(PROBLEM1 = 0) as COUNTERRORS
FROM TABLE1
GROUP BY Date, Name;

How to Selecting 2 query to single statment?

I have two select statement for find avg economy for car I need connect to single statement. I tired but showig error
Basically in first statement includes cast, avg, nullif groupby
In second statement contains where, when, case then
SELECT vehicle_id,CAST(AVG((NULLIF(economy,0))) AS int) FROM fillups group BY vehicle_id
WHERE vehicle_id <= 2 THEN 'Prius'
AND
vehicle_id >= 2 THEN 'Other';
Thats the code when put into single statement
Select vehicle_id, CAST(AVG((NULLIF(economy,0))) AS int),
when vehicle_id < 2 then 'Prius'
when vehicle_id >= 2 then 'other'
from fillups
group by vehicle_id
This may help !!
If not please mention some data schema structure.
Please try this:
Select vehicle_id, CAST(AVG((NULLIF(economy,0)) as int) as columnA,
case when vehicle_id < 2 then 'Prius'
when vehicle_id >= 2 then 'other'
end as columnB
from fillups
group by vehicle_id

Count DISTINCT on a single column over multiple conditions

I have a table, and I want to get the DISTINCT count of usernames over a certain period of time. Currently I'm running this query
SELECT DISTINCT username FROM user_activity WHERE company_id = 9 AND timestamp BETWEEN '2015-09-00' AND '2015-10-01' AND action = "Login Success";
It works great, however, I have multiple Companies that I want to select the count for. How do I expand the previous query to show me the distinct counts for multiple companies?
select count(distinct username),
sum(case when company_id = 1 then 1 else 0 end) A,
sum(case when company_id = 9 then 1 else 0 end) B
from `user_activity` Where timestamp BETWEEN '2015-09-00' AND '2015-10-01' AND action = "Login Success"
I've done something like this, however, I'm not getting the correct numbers. Ideally I would like to list each count as a different value for ease of reading, like the previous query illustrates. I don't need the count(distinct username) column to appear in my result, just the conditionals.
Thanks in advance.
If you don't mind two rows instead of two columns:
SELECT company_id, COUNT(DISTINCT username)
FROM user_activity
WHERE company_id IN (1,9)
AND timestamp >= '2015-09-01'
AND timestamp < '2015-09-01' + INTERVAL 1 MONTH
AND action = "Login Success"
GROUP BY company_id

select case when not working as expected

I'm trying to understand how this works but can't figure it out yet.
I have made this simple uery to test the case-when-then-end clause...
SELECT case when quantity > 3
then count(*) end the_count_a,
case when quantity <= 3
then count(*) end the_count_b
FROM STOCK
my stock table has 30 items with different quantities, only 10 items have quantity over 3 but this is always returning 30.... WHY?
I think it should be returning two columns with values: 10 and 20
Any help will be appreciated!
Thx,
Leo
The value of count(*) means the count of all records (in the current group), regardless of where it is placed. If you want to count records that match a condition, you need to invert your case statement:
select count(case when quantity > 3 then 1 end) the_count_a,
count(case when quantity <= 3 then 1 end) the_count_b
from stock
SELECT
count(case when quantity > 3 then 1 else null end) end the_count_a,
count(case when quantity <= 3 then 1 else null end) end the_count_b
FROM STOCK
The aggregate function COUNT() in absense of a GROUP BY will return all rows in the table which have not been filtered by a WHERE clause. In your case, what you actually need are two subselects or a UNION, depending if you want columns or rows back:
/* Return columns with subselects */
SELECT
(SELECT COUNT(*) FROM STOCK WHERE quantity > 3) AS the_count_a
(SELECT COUNT(*) FROM STOCK WHERE quantity <= 3) AS the_count_b
MySQL is lenient about the presence of a FROM clause, so it can be omitted from the outer query.
/* Return rows instead of columns with UNION */
SELECT
COUNT(*) AS the_count,
'the_count_a'
FROM STOCK WHERE quantity > 3
UNION ALL
SELECT
COUNT(*) AS the_count,
'the_count_b'
FROM STOCK WHERE quantity <= 30

mysql query: how to get the number of yes/no votes per day

I have to create a mysql query to get a voting distribution of each day exceeding a particular date, something like this...
date yes_votes no_votes
------------------------------------------
2010-01-07 21 22
2010-01-07 2 0
My table is like this..
post_votes
--------------------------
id(longint)
date(timestamp)
flag(tinyint) // this stores the yes/no votes 1-yes, 2-no
I am stuck at this....
SELECT COUNT(*) AS count, DATE(date) FROM post_votes WHERE date > '2010-07-01' GROUP BY DATE(date)
this gives the total number of votes per day, but not the distribution that I want.
SELECT COUNT(*) AS count
, DATE(date)
, SUM(flag = 1) AS yes_votes
, SUM(flag = 2) AS no_votes
FROM post_votes
WHERE date > '2010-07-01'
GROUP BY DATE(date)
This is a trick that works in MySQL, as flag=1 will either be True or False. But True = 1 and False = 0 in MySQL so you can add the 1s and 0s using the SUM() function.
Other solutions with IF or CASE would be better for clarity or if there is any chance you want to move the database to another RDBMS.
Comments not related to the question:
It's bad habit to use reserved words like date or count for naming fields or tables.
It's also not good to use "date" when you actually store a timestamp. Names should reflect use.
For table names it's recommended to use singular (post_vote) and not plural - although many use plural, it gets confusing in the end. Plural is good for some fields or calulated fields, like your yes_votes and no_votes where we have a counting.
Sum it:
select date(date) as date,
sum(case when flag = 1 then 1 else 0) as yes,
sum(case when flag = 2 then 1 else 0) as no
from post_votes
where date > '2010-07-01'
group by date(date)
you are almost at the solution :)
i would recommend the use of an IF condition in a SUM method like so:
SELECT SUM(IF(flag = 'yes',1,0)) AS yes_count,
SUM(IF(flag = 'no',1,0)) AS no_count,
DATE(date)
FROM post_votes
WHERE date > '2010-07-01'
GROUP BY DATE(date)
this will allow for the function to add 1 to each sum only if the value is equal to yes/no
SELECT DATE(date) as dt,
sum(if(flag=1,1,0)) as yes,
sum(if(flag=2,1,0)) as no
FROM post_votes WHERE date > '2010-07-01'
GROUP BY dt
I had that problem too. The best solution of that I can think of, is to split the "flag" in two fields, like:
upvote(tinyint)
downvote(tinyint)
Then you are able to count them very easy and without mysql-voodoo:
SELECT
SUM(upvote) AS up,
SUM(downvote) AS down,
DATE(`date`) AS Created_at
FROM post_votes
WHERE Created_at > '2010-07-01'
GROUP BY Created_at
Btw.: You should not name a column date, because it's a MySQL-Keyword.