SQL query count = 0/null - mysql

I have the following MySql table with ~19000 entries like this:
ID USER FIELD1 FIELD2 SOMEINT ERROR
1 name1 null null null missing...
2 name1 value1 value2 3 validated!
3 name1 value3 wrongvalue1 null syntax
4 name2 wrongvalue2 value4 null syntax
etc...................................................................
I would like to get a list like this:
USER totalEntries totalValid totalMissing totalSyntax
name1 3 1 1 1
name2 1 0 0 1
etc...................................................................
I have a query for every column like this:
select user, count(user) valid from table where
someint is not null group by user limit 0, 20000;
(total valid entries)
select user, count(*) totalEntries from table group by user
limit 0, 20000; (total entries)
select user, count(*) totalMissing from table where field1 is null or
field2 is null group by user limit 0, 20000; (total Missing entrie)
select user, count(*) syntax from table where error like 'syntax%'
group by user limit 0, 20000 (syntaxerror entries)
The problem is that "group by" does not list the count(...) entries as
USER valid
...
name3 0
So the 4 query results do not have the same rowcount. How can I solve this Problem?

You are trying to do this:
SELECT user, COUNT(*) as totalEntries,
SUM(CASE WHEN someint IS NOT NULL THEN 1 ELSE 0 END),
SUM(CASE WHEN field1 IS NULL OR field2 IS NULL THEN 1 ELSE 0 END),
SUM(CASE WHEN error LIKE 'syntax%' THEN 1 ELSE 0 END)
FROM SomeTable
GROUP by user
User Name
Number of entries of the user
Number of entries of entries with some int different of NULL
Number of entries where Error ismissing`
Number of entries where ERROR is syntax
PD: Maybe you want to add the LIMIT 0,20000 at the end of the query. I didn't do that because I didn't get the purpose.

Related

How to select data in mysql that all the joined table is not null on certain column

i have 2 table which is one to many
table order
order_id
order_date
1
2021/01/01
2
2021/01/02
3
2021/01/02
table detail order
detail_order_id
order_id
is_finished
1
1
null
2
1
2021/01/03
3
2
2021/01/04
4
2
2021/01/04
5
3
2021/01/05
6
3
2021/01/06
7
3
null
so i wanna data that have condition if some of the detail order rows is_finished column not null, so the status is gonna be not finish.
and if all the detail order rows is_finished column not contain any null value like id 2, so the status is finished
expected result
order_id
status
1
not finish
2
finished
3
not finish
It seems like you don't really need a join since table_detail_order already have order_id and you only want to check is_finished, you might just need a query on 1 table like:
SELECT order_id,
CASE WHEN SUM(is_finished IS NULL)=0
THEN 'Finished' ELSE 'Not finish' END AS 'Status'
FROM table_detail_order GROUP BY order_id;
Demo fiddle
Btw, is_finished IS NULL will return 1 (true) or 0 (false) so in a table it would look like:
order_id
is_finished
is_finished IS NULL
1
null
1
1
2021/01/03
0
2
2021/01/04
0
2
2021/01/04
0
3
2021/01/05
0
3
2021/01/06
0
3
null
1
Therefore SUM(is_finished IS NULL) with GROUP BY order_id; will do something like this:
order_id
SUM(is_finished IS NULL)
1
1+0=1
2
0+0=0
3
0+0+1=1
And that is why CASE WHEN SUM(is_finished IS NULL)=0 ... is considered as finished while otherwise as not finish.
we can solve the problem like this
left join order and order_detail,but has condition order_details.is_finished is null
so we get a result that the joined order_details's is_finished only null
in that case there is no order_details join with order 2
then we regard the result as a temp table,so when joined order_details has data then it is not finished
here is the example data,you can run query in it
select id,
case when order_id>0 then 'not finish' else 'finished' end as status
from (
select o.id,od.order_id from `order` as o
left join order_detail as od
on (o.id=od.order_id and od.is_finished is null)
group by o.id
) as _t
You can try this. This query uses a LEFT JOIN and COUNT. Where the first count counted the NULL values as ZERO and the second count counts all values, then compare the 2 counts, if the first and second count is equal to each other it means that the order details is finished, if not then not finish.
SELECT a.`order_id`,
IF(COUNT(IF(ISNULL(is_finished),0,1))=COUNT(is_finished), 'finished', 'not finish') AS `status` FROM `order` a
LEFT JOIN `detail_order` b ON a.`order_id`=b.`order_id`
GROUP BY a.`order_id` ;
RESULT*
order_id status
-------- ------------
1 not finish
2 finished
3 not finish

SQL Sub queries Seat Exchange

I am trying to understand how this subquery works. The questions are as follows
Mary is a teacher in a middle school and she has a table seat storing students' names and their corresponding seat ids.The column id is continuous increment.
Mary wants to change seats for the adjacent students.
SELECT
(CASE
WHEN MOD(id, 2) != 0 AND counts != id THEN id + 1
WHEN MOD(id, 2) != 0 AND counts = id THEN id
ELSE id - 1
END) AS id,
student
FROM
seat,
(SELECT
COUNT(*) AS counts
FROM
seat) AS seat_counts
ORDER BY id ASC;
I am trying to understand the how the above query works. So in the CASE it checks if the id is odd or even and checks against the count to see if it is the last element. But how does the ORDER BY ASC work? Because for the first time it selects student Dorris and id 2. but then how is id 2 assigned to Abbot. Thanks.
SQL Table
id | student
1 | Abbot
2 | Doris
3 | Emerson
4 | Green
5 | Jeames
The Result will look like
id | student
1 | Dorris
2 | Abbot
3 | Green
4 | Emerson
5 | Jeames
OK what this is doing is the following -- if an id number is odd and it is not the max number then add one to it, otherwise subtract one from it.
It should be clear that would swap all but the last pair.
I think it is badly written I would write it like this:
WITH student_count(max) as
(
SELECT COUNT(*) FROM seat
)
SELECT
CASE
WHEN student_count.max != id AND MOD(id, 2) != 0 THEN id + 1
WHEN student_count.max != id AND MOD(id, 2) = 0 THEN id - 1
ELSE id
END AS id,
student
FROM seat
CROSS JOIN student_count
ORDER BY id ASC;
I would recommend you to check the results by removing ORDER BY statement. When you remove ORDER BY statement, result will be:
2 Abbot
1 Doris
4 Emerson
3 Green
5 Jeames
Which is completely right for your case. Basically, your query just alters id's values based on the CASE statement. When you add ORDER BY id ASC statement it just orders the result above.
select name,
case when mod(seat_id,2) = 1 and seat_id <> (select max(seat_id) from students) then seat_id + 1
when mod(seat_id,2)= 0 then seat_id - 1
when mod(seat_id,2) = 1 and seat_id = (select max(seat_id) from students) then seat_id
end swap
from students
SELECT
(CASE
WHEN MOD(id, 2) != 0 AND counts != id THEN id + 1
WHEN MOD(id, 2) != 0 AND counts = id THEN id
ELSE id - 1
END) AS id,
student
FROM
seat,
(SELECT
COUNT(*) AS counts
FROM
seat) AS seat_counts
ORDER BY id ASC;

sql Get count of X that do not have a Specific Y value in Group by X, Y

In a given table, There are 2 important fields. One field is a foreign key like field, in this case, userID the other is a status field. the data types do not matter, but for the sake of simplicity, both are integers. Status field has a limited number of outputs, again for simplicity, a 0 or a 1. the foreign key can of course be any reasonable integer.
The following query would have up to 2 rows per userID, totaling the number of rows with each status
SELECT userID, Status, count(Status) as total FROM tbl Group by userID, Status
if run on an example table, it would look something like
userID Status total
1 0 5
1 1 2
2 1 2
4 0 6
For this Imaginary table, This means the user with ID 1 has 7 rows in this table, 5 of which are of status 0, while the other 2 are of status 1. user ID 2 has only 2 rows of status 1, user ID 3 has no rows in this table, and 4 has 6 of status 0.
How can one further refine this so that only rows with Status of 0 are returned, but Only when the userID does not have any rows with status 1. In the above case, the only row returned would be
userID Status total
4 0 6
Use a conditional COUNT to calculate how many 1's are in the group.
Sql Fiddle Demo
SELECT u.userID, u.Status, count(u.Status) as total
FROM users u
JOIN (SELECT userID
FROM users
GROUP BY userID
HAVING COUNT(CASE WHEN Status = 1 THEN 1
ELSE NULL
END) = 0
) f -- filter
ON u.userID = f.userID
GROUP BY userID, Status;
else null is optional for better read, but can be removed
OUTPUT
| userID | Status | total |
|--------|--------|-------|
| 4 | 0 | 6 |
SUM also work.
HAVING SUM(case when status = 1 then 1 else 0 END) = 0

counting with conditions in mysql

im a bit stuck in a quite simple query
i have these 4 columns in the table
id1 (unique), id2 (can repeat) , updated (boolean), updated_on
what i want now is to get a summary in the form
id2, count of updates , max (updated_on)
in short i want the result sorted by the recent updated_on while counting all rows for this id2 where update=1
and for ids that donot have any update=1, show 0, with the max updated_on
______________________
id2|_count__|___date__
1 | 0 | 11/03/05,
3 | 5 | 11/03/04,
6 | 3 | 11/03/03,
2 | 0 | 11/03/02,
i used this query :
select id2, count(updated),max(updated_on) from table
where updated=1
group by need_id_to
but this query doesnot bring results where count would be 0 (for obvious reasons because im adding a condition in the where clause)
A boolean field is 1 for true and 0 for false.
You can use this to get the count of all updated = true rows.
SELECT
id2
, SUM(updated) as updates
,MAX(updated_on) as last_update
FROM table1
GROUP BY id2
ORDER BY last_update DESC
select id2,
count(case
when updated=1 then updated
else null
end) updates_count,
max(updated_on) last_updated
from table
group by id2
order by last_updated desc
select id2,
SUM(CASE WHEN updated=1 THEN 1 ELSE 0 END) AS UpdatedCount,
max(updated_on)
from table
group by id2

MySQL merge amounts in a 2 rows

I'm looking to create a sql statement that will update a large set of data.
What I have is a table like
id, transid, amount, narative1, narative 2, total, active
1 1234 23.2 NULL NULL NULL 1
2 1234 120.33 NULL NULL NULL 1
3 1235 98.00 NULL NULL NULL 1
When there are two rows with the same transid I need to total them put the result in the total column of the first one with that transid and put the second amount in naritive2 of the first instance as well as make the second one inactive. It should ignore single rows for a transid.
The result of what I want to do should be:
id, transid, amount, narative1, narative 2, total, active
1 1234 23.2 NULL 120.33 143.53 1
2 1234 120.33 NULL NULL NULL 0
3 1235 98.00 NULL NULL NULL 1
I know a bit of a thong twister but..
Ideally I'd like to do this in just a MySQL statements. So I don't mind having to do multiple sql statements but I want to avoid connecting it to PHP etc. Its a very large set of data.
This will update only those transactions that have exactly 2 rows (not 1 and not 3 or more).
UPDATE mytable mtu
JOIN (
SELECT minid, maxid, mtmin.amount AS minamt, mtmax.amount AS maxamt
FROM (
SELECT MIN(id) AS minid, MAX(id) AS maxid
FROM mytable mti
GROUP BY
transid
HAVING COUNT(*) = 2
) mt
JOIN mytable mtmin
ON mtmin.id = minid
JOIN mytable mtmax
ON mtmax.id = maxid
) mts
ON id IN (minid, maxid)
SET narative2 = CASE id WHEN minid THEN minamt ELSE NULL END,
total = CASE id WHEN minid THEN minamt + maxamt ELSE NULL END,
active = (id = minid)