Find duplicates in mySQL but with a specific status - mysql

I have an orders table and I need to find the duplicates - orders which have the same dd_number and dd_code, BUT one of the orders must have the status of "checkout_completed".
The following is my current SQL which correctly finds duplicate orders which have the same dd_number and dd_code, however I cant work out how to check for the status:
SELECT
tbOrders.id, tbOrders.dd_number, tbOrders.dd_code, tbOrders.status, COUNT(*) AS totalDupes
FROM
tbOrders
WHERE
dd_number IS NOT NULL
AND
dd_number != ''
AND
dd_number != '000000'
AND
dd_number != '00000000'
GROUP BY
dd_number, dd_code
HAVING totalDupes > 1
Adding a WHERE clause of status = 'checkout_complete' does not work as it requires both orders to have the same status. Any help would be greatly appreciated!

SELECT
tbOrders.id, tbOrders.dd_number, tbOrders.dd_code, tbOrders.status, COUNT(*) AS totalDupes,
SUM(CASE WHEN status='checkout_complete' THEN 1 ELSE 0 END) as status_count
FROM
tbOrders
WHERE
dd_number IS NOT NULL
AND
dd_number != ''
AND
dd_number != '000000'
AND
dd_number != '00000000'
GROUP BY
dd_number, dd_code
HAVING totalDupes > 1 and status_count=1
You can introduce one more aggregate field counting records with the status

Mmm, multiple way of doing it. I'd suggest using the HAVING clause with conditional aggregation :
HAVING totalDupes > 1
AND MAX(CASE WHEN status = 'checkout_complete' THEN 1 ELSE 0 END) = 1
Though your query seems wrong. If ID is unique, then a random ID will be choosen , same goes for STATUS . All the columns should either be in the GROUP BY or wrapped with an aggregation function. Note that only MySQL older versions accept your syntax. In any other RDBMS this will throw an error.

Related

how to get the desired result based on some certain condition in sql using case?

I have a table which traces the users records I want to know which are the complete and process users's records based on their status
Here is the sql query
SELECT users.UserID,users.UserName,users.FirstName,users.LastName,users.Email,
CASE WHEN inword.inword_status = '3' THEN count(*) END As 'Process' ,
CASE WHEN inword.inword_status = '4' THEN count(*) END AS 'Complete'
FROM tbl_user users
INNER JOIN tbl_inword inword on users.UserID=inword.UserID
Where inword.Status=1 and users.Status=1 and
inword.CreatedDate BETWEEN '2020-10-01' and '2020-10-31' and inword.inword_status in (3)
group by users.UserID
Here is Query Output
My Expected result is
UserID Name Total Process Complete
1 Umair 1 1 0
1 Basit 20 20 0
1 Zaidi 34 32 2
Any Help would be Appreciated
You're not doing your conditional aggregation correctly, you should use something like:
COUNT(CASE WHEN inword.inword_status = '3' THEN inword.UserId END) As 'Process' ,
COUNT(CASE WHEN inword.inword_status = '4' THEN inword.UserId END) AS 'Complete'
Or you can take advantage of MySQL treating booleans as 1 or 0 in a numeric context and simplify to:
SUM(inword.inword_status = '3') As 'Process' ,
SUM(inword.inword_status = '4') AS 'Complete'

MySQL Select count rows with specific attribute

Sorry for the title, but my problem it's difficult to explain.
I have a table called "TEL_LIST" with this fields:
ID
TELEPHONE
STATUS
I have many rows for a single telephone number. The status may be YES or NO.
I want to count the total number of rows with status "NO" (without counting the "YES" rows) only for telephone numbers which have at least one "YES" status.
To make you understand better, I want this:
EDIT:
TEL:011, STATUS:YES
TEL:011, STATUS:NO
TEL:011, STATUS:NO
TEL:012, STATUS:NO
TEL:012, STATUS:NO
TEL:012, STATUS:NO
RESULT: 2.
TEL:011, STATUS:YES
TEL:011, STATUS:NO
TEL:011, STATUS:NO
TEL:012, STATUS:YES
TEL:012, STATUS:NO
TEL:012, STATUS:NO
RESULT: 4.
Perhaps I have not explained well:
I want the total number (the sum) of all "No" records which have at least one "Yes" record.
To make you understand well, I work in a contact center. I want the total of all negative calls (status: no) that have become positive (status: yes).
Thank you again!
I think this follows your logic:
select tel,
(case when sum(status = 'Yes') = 0 then 0
else sum(status = 'No')
end)
from t
group by tel;
I think maybe this can help me:
select count(case when STATUS != 'YES' Then 1 end) AS TOT
from T
having (select count(case when STATUS='YES' Then 1 end) AS T)>0 AND TOT>0
I tried this solution but I'm not sure that the result is correct...
I would use a left join and a group by query:
select t1.tel, count(t2.tel) AS total_no
from
TEL t1 left join TEL t2
on t1.tel=t2.tel AND t1.status='Yes' AND t2.status='No'
group by
t1.tel
with an index on tel and status, performances should be optimal. Numbers that don't have any status='Yes' won't be returned.
Try this one:
select x.Tel, count(distinct x.Number)
from (
select t.Tel, case when tmp.tel is not null then Id else null end as Number
from yourtable t
left outer join (
select tel
from yourtable
where status = 'Yes'
) tmp on tmp.Tel = t.Tel
where t.status = 'No'
) x
group by x.tel
Use Conditional Aggregate to count the values
select TEL,
count(case when STATUS = 'Yes' Then 1 end) AS Conditional_Count
from yourtable
Group by TEL
Another way would be
SUM(case when STATUS = 'Yes' Then 1 ELSE 0 end)
Update: Based on the clarification in question
select count(case when STATUS = 'NO' Then 1 end) AS Conditional_Count
from yourtable
Having count(case when STATUS = 'YES' Then 1 end) > 0

MySQL Count multiple columns at once or separate transactions

I have a daily cron that counts the number of non-null and non-empty string rows for a specific column, such as:
SELECT count(first_name) FROM users WHERE first_name IS NOT NULL and first_name IS != ''
SELECT count(last_name) FROM users WHERE last_name IS NOT NULL and first_name IS != ''
Would the performance be improved if I did this in one MySQL call?
Use a CASE condition for 1 query
SELECT SUM(CASE WHEN first_name IS NOT NULL and first_name != '' THEN 1 ELSE 0 END),
SUM(CASE WHEN last_name IS NOT NULL and last_name != '' THEN 1 ELSE 0 END) FROM users
I believe that this query is enough:
SELECT COUNT(DISTINCT first_name), COUNT(DISTINCT last_name) FROM users
As other developers pointed this COUNT will count even '' empty value.
IMHO that is acceptable. If not you can:
SELECT COUNT(DISTINCT first_name)-1, COUNT(DISTINCT last_name)-1 FROM users
It is not exactly what you need, but if you are sure that you have those empty value that will work :
If you want clear query that return correct COUNT you should better use #Mihai query:
SELECT SUM(CASE WHEN first_name IS NOT NULL and first_name != '' THEN 1 ELSE 0 END),
SUM(CASE WHEN last_name IS NOT NULL and last_name != '' THEN 1 ELSE 0 END) FROM user
But this one can hit the performance a lot on big numbers of records.

How to get multiple SUM with one SQL query?

I am wondering how to fix this query.
SELECT
SUM(`month_using`) used,
SUM(`month_cash`) paycash,
SUM(`month_profit` CASE WHEN `id` <> 'system' THEN 1 ELSE 0 END) profit
FROM `_using_month`
WHERE MONTH(`month_date`) = {month} AND YEAR(`month_date`) = {year}
Thanks
Use Group by clause to get multiple SUM:
For Example:
SELECT YEAR(month_date), MONTH(month_date),
SUM(month_using) used, SUM(month_cash) paycash,
SUM(month_profit CASE WHEN id <> 'system' THEN 1 ELSE 0 END) profit
FROM _using_month
GROUP BY YEAR(month_date), MONTH(month_date)

Laravel group by and SUM

Having trouble getting my head around this one, it likely doesn't help I don't have any SQL 'group by' experience.
I have a table that has a transaction_type column and an amount column. Basically I am trying to use SQL/Eloquent to get the following in a single query (if possible, I know this isn't sql):
add = SUM(amount) where transaction_type == 1
delete = SUM(amount) WHERE transaction_type == 2
return from MySQL: add-delete
I'm assuming this would be done using groupby, but despite my best efforts I haven't be able to find a solution by reading the sql documentation.
I think I have got it using plain SQL, but how would I convert this to Eloquent:
SELECT `transaction_type`, SUM(`amount`) FROM `credit_logs` WHERE `to_group_id` = '1'
I can't help you with eloquent, but your query should be something like this:
SELECT
SUM(CASE WHEN transaction_type = 1 THEN amount ELSE NULL END)
-
SUM(CASE WHEN transaction_type = 2 THEN amount ELSE NULL END)
FROM credit_logs
WHERE to_group_id = 1;
or for all id's you wish to group by:
SELECT
SUM(CASE WHEN transaction_type = 1 THEN amount ELSE NULL END)
-
SUM(CASE WHEN transaction_type = 2 THEN amount ELSE NULL END)
FROM credit_logs
GROUP BY to_group_id;
Easiest would be, if you'd find a way to just execute a query with eloquent. Never understood why someone wants to transform a nice readable query into some "improved" syntax of a framework.