How to Get Row Count Depending on Column Values using MySQL - mysql

I am querying a mysql table and want results group by date, and one column name is type. There are two value for the type call and email. I want to find count for call and email for each day.
Find the SQL Fiddle here
I am trying with this query. Which only gets me total counts:
SELECT Date(date) date,
COUNT(type) total,
COUNT(type='email') emails,
COUNT(type='call') calls
from leads
where user_id = 1
GROUP BY Date(date)

Use SUM() instead. The type='email' in the function returns either 0 (false) or 1 (true).
SELECT Date(date) date,
COUNT(type) total,
SUM(type='email') emails,
SUM(type='call') calls
from leads
where user_id = 1
GROUP BY Date(date)

Related

MySQL Using merging two identical tables and use GROUP BY

I want to select from two identical tables using UNION ALL and GROUP BY. However, the Group BY doesn't work. Here is my query:
SELECT type , COUNT(subscription.id) as number ,SUM(subscription.amount) as total
FROM subscription
WHERE DATE(subscription.timestamp) BETWEEN '2022-10-18' AND '2022-10-18'
UNION ALL
SELECT type , COUNT(archive_subscription.id) as number ,SUM(archive_subscription.amount) as total
FROM archive_subscription
WHERE DATE(archive_subscription.timestamp) BETWEEN '2022-10-18' AND '2022-10-18'
GROUP BY type
The result is like the following:
type
number
amount
1
2
180000
1
1
80000
What I want to do is two merge both table using GROUP BY but it won't work:
type
number
amount
1
3
260000
Please, any suggestions? Thanks
The first subquery in your union is missing its GROUP BY clause. Instead, try taking a union first and then aggregate:
SELECT type, COUNT(*) AS number, SUM(amount) AS total
FROM
(
SELECT type, amount
FROM subscription
WHERE timestamp BETWEEN '2022-10-18' AND '2022-10-18'
UNION ALL
SELECT type, amount
FROM archive_subscription
WHERE timestamp BETWEEN '2022-10-18' AND '2022-10-18'
) t
GROUP BY type;
Note that the ranges in your WHERE clauses are trivial. If you really want to restrict to a single date, just use WHERE timestamp = '2022-10-18' instead.

How to count total row on MySQL based upon month and year

My database table contains value in this way
IMAGE FOR TABLE DATA
I want to track down same email which has been used more than one times for a particular month and year.
In the above scenario, email that has been repeated multiple times was sandeshphuya#gmail.com, jes#gmail.com and ramu#gmail.com for different months. I want to track down customer repetition following their email for each month and year.
The query that I am using right now is
SELECT DATE_FORMAT(booked_on, '%Y-%m') as monthYear, email,
COUNT(*) AS 'Count'
FROM 'tablename'
GROUP BY email,DATE_FORMAT(booked_on, '%Y-%m') HAVING COUNT(*) > 1 ORDER BY `booked_on`;
GROUP BY email was used as it generates the repeated email and GROUP BY DATE_FORMAT(booked_on, '%Y'-%m') was used to track down total email repeated for each month/year.
This prints out data as
IMAGE FOR SELECT QUERY
How can I track down total repeated email following month and year? The expected result is
RESULT EXPECTED
You can use your query as a subquery for a new group by:
select sub.monthYear,count(*)
from
(SELECT DATE_FORMAT(booked_on, '%Y-%m') as monthYear,
email,
COUNT(*) AS 'Count'
FROM 'tablename'
GROUP BY email,DATE_FORMAT(booked_on, '%Y-%m')
HAVING COUNT(*) > 1
ORDER BY `booked_on`) as sub
GROUP BY sub.monthYear

related to query using SQL

In oracle sql, how to get the count of newly added customers only for the month of april and may and make sure they werent there in the previous months
SELECT CUSTOMER ID , COUNT(*)
FROM TABLE
WHERE DATE BETWEEN '1-APR-2018' AND '31-MAY-2018' AND ...
If we give max (date) and min(date), we can compare the greater date to check if this customer is new , correct?
expected output is month count
april ---
may ---
should show the exact count how many new customers joined in these two months
One approach is to use aggregation:
select customer_id, min(date) as min_date
from t
group by customer_id
having min(date) >= date '2018-04-01 and
min(date) < date '2018-06-01';
This gets the list of customers (which your query seems to be doing). To get the count, just use count(*) and make this a subquery.

SQL Error Code 1055. Minimum date by Flag by Group

I'm trying to find the minimum date at which patient took a drug with a certain flag. Here is the code I'm using:
create table Schema.Want as select
*, min(case when Flag="True" then Date end) as First_Date
from Schema.Have group by Patient_ID;
I have also tried listing out all the variables, but that didn't help either. When I run that code I get the Error Code 1055 associated with "only_full_group". I've seen others suggesting that I turn this off (which I have NOT tried yet) but I'm concerned about why this error is being thrown in the first place. When I get this error code, does that mean that I have duplicate rows in my table?
I've got Patient_ID(NUM), Drug_ID(NUM), Quantity(NUM), Fill_Date (Date/Char), Flag(CHAR), Comp_Set(CHAR), and Drug_strength(CHAR). So if one patient filled two prescriptions for the same strength and quantity of the same exact drug on the same day, then two of their rows would be identical. That doesn't seem likely to me though.
All I need to do is create a separate column with the oldest date at which a patient was prescribed a certain drug. My code worked using proc sql in SAS, but not when I use MySQL. Thanks for your help in advance!!
You need to remerge the MIN() value back onto the detail records. If you check the log in SAS you will see that it says that it is doing the remerge for you.
create table Schema.Want as
select a.*,b.First_Date
from Schema.Have a
inner join
(select Patient_ID, min(case when Flag="True" then Date end) as First_Date
from Schema.Have group by Patient_ID) b
on a.Patient_ID=b.Patient_ID
;
Use select into:
select
*, min(case when Flag="True" then Date end) as First_Date into Schema.Want
from Schema.Have group by Patient_ID
Also replace * with column names and group by all names
All the values you have in the Select except the min must also be in the group by clause.
create table Schema.Want as select
Patient_ID, min(case when Flag="True" then Date end) as First_Date
from Schema.Have group by Patient_ID;
Note: If you have other numeric variables in the select; you will have to give them an aggregate function (min, max, avg ..) and not include them in the group by .
I recommend doing a select only in SQL before deciding to create the table:
select Patient_ID, min(case when Flag="True" then Date end) as First_Date
from Schema.Have group by Patient_ID;

Why is 'ORDER BY' needed to get correct result from MySQL join?

I have the following query:
SELECT t.ID, t.caseID, time
FROM tbl_test t
INNER JOIN (
SELECT ID, MAX( TIME )
FROM tbl_test
WHERE TIME <=1353143351
GROUP BY caseID
ORDER BY caseID DESC -- ERROR HERE!
) s
USING (ID)
It seems that I only get the correct result if I use the ORDER BY in the inner join. Why is that? I am using the ID for the join, so the order should take no effekt.
If I remove the order by, I get too old entries from the database.
ID is the primary key, the caseID is a kind of object with multiple entries with different timestamps.
This query is ambiguous:
SELECT ID, MAX( TIME )
FROM tbl_test
WHERE TIME <=1353143351
GROUP BY caseID
It's ambiguous because it does not guarantee that it returns the ID of the row where the MAX(TIME) occurs. It returns the MAX(TIME) for each distinct value of caseID, but the value of other columns (like ID) is chosen arbitrarily from members of the group.
In practice, MySQL chooses the row that it finds first in the group as it scans rows in storage order.
Example:
caseID ID time
1 10 15:00
1 12 18:00
1 14 13:00
The max time is 18:00, which is the row with ID 12. But the query will return ID 10, simply because it's the first one in the group. If you were to reverse the order with ORDER BY, it would return ID 14. Still not the row where the max time is found, but it's from the other end of the group of rows.
Your query works with ORDER BY caseID DESC because, by coincidence, your Time values increase with the increasing ID.
This sort of query is actually an error in standard SQL and most other brands of SQL database. MySQL permits it, trusting that you know how to form an unambiguous query.
The fix is to use columns in the select-list only if they are unambiguous, that is, if they are in the GROUP BY clause, then each group is guaranteed to have only one distinct value:
SELECT caseID, MAX( TIME )
FROM tbl_test
WHERE TIME <=1353143351
GROUP BY caseID
SELECT t.ID, t.caseID, time
FROM tbl_test t
INNER JOIN (
SELECT caseID, MAX( TIME ) maxtime
FROM tbl_test
WHERE TIME <=1353143351
GROUP BY caseID
) s
ON t.caseID = s.caseID and t.time = s.maxtime
You are seeing that issue because you are getting the MAX(TIME) per caseID, but since you are grouping by caseID and NOT ID, you are getting an arbitrary ID. That happens because when you use an aggregate function, like MAX, you must, for every non-grouped field in the select specify how you want to aggregate it. That means, if it's in the SELECT and NOT in the GROUP BY, you have to tell MySQL how to aggregate. If you don't then you get a RANDOM row (well, not random per se, but it's not going to be in an order that you necessarily expect).
The reason ORDER BY is working for you, is that it kind of tricks the query optimizer into sorting the results before grouping, which just so happens to produce the result you want, but be warned, that will not always be the case.
What you want is the ID that has the MAX(TIME) given a caseID. Which means your INNER join needs to connect by caseID (not ID) and time (which will give you 1 row per each 1 row in the outer table).
Barmar beat me to the actual query, but that's the way you want to go.